Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐘
🐘 Packagist
Not in CISA KEV
HIGH severity

CVE-2026-55416

HIGH

CVE-2026-55416 is a high-severity (CVSS 8.8) vulnerability in pimcore/pimcore. O3 Security confirms whether CVE-2026-55416 is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

Pimcore: SQL Injection in Custom Reports via Malicious Report Configuration

Published
Sep 10, 2026
Updated
Sep 10, 2026
Affected
3 pkgs
Patched
3 / 3
Exploits
None indexed
Exploitation data as of Sep 10, 2026 · OSV.dev, FIRST.org (EPSS)

Real-World Exposure

3 pkgs affected
🐘pimcore/pimcore🐘pimcore/pimcore🐘pimcore/pimcore

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.

Description

Security Advisory: SQL Injection in Custom Reports via Malicious Report Configuration

Summary

Impact

A SQL injection vulnerability exists in the Custom Reports bundle (bundles/CustomReportsBundle/src/Tool/Adapter/Sql.php:84-135). An authenticated attacker with reports_config permission can inject arbitrary SQL via the report configuration fields (sql, from, where, groupby), which are directly concatenated into SQL queries without parameterization. The only protection is a regex blacklist that checks for ALTER|CREATE|DROP|RENAME|TRUNCATE|UPDATE|DELETE keywords, which is trivially bypassable — it does not block INSERT, UNION SELECT, LOAD_FILE(), INTO OUTFILE, stacked queries, subqueries, or MySQL comment injection (/*!*/). Exploitation allows reading, modifying, or deleting all data in the database, leading to complete data compromise.

Additionally, the LIMIT clause at line 51 directly interpolates $offset and $limit without integer casting, creating a secondary injection point.

Patches

Versions 2026.1.6, 12.3.10, 11.5.19.

Workarounds

  1. Restrict reports_config permission to only highly trusted administrators
  2. Deploy a WAF rule to block requests to /admin/bundle/customreports/custom-report/update containing SQL keywords in the configuration parameter
  3. Replace the custom SQL adapter with a parameterized query builder approach

Attack Path (Validation Evidence)

[Entry Point] POST /admin/bundle/customreports/custom-report/update HTTP/1.1
    ↓ (requires reports_config permission + valid admin session)
[Controller] CustomReportController::updateAction()
    ↓  $configuration = decodeJson($request->request->getString('configuration'))
[Config Store] Configuration saved to custom_reports database table
[Config Load] Tool\Config::getByName() loads stdClass $config from DB
    ↓
[Adapter] Sql::getBaseQuery() → Sql::buildQueryString($config)
    ↓  Directly concatenates config fields:
[Vulnerable] $sql .= "\n" . $config['sql'];        // Line 92
            $sql .= "\n" . $config['from'];        // Line 103
            $sql .= "\n" . 'WHERE (' . $config['where'] . ')'; // Line 110
            $sql .= "\n" . $config['groupby'];     // Line 117
[Weak Guard] preg_match('/(ALTER|CREATE|DROP|RENAME|TRUNCATE|UPDATE|DELETE)\s/i', ...)
    ↓  ✗ Bypassable — missing INSERT, UNION, SELECT, subqueries, comments
[Execution] $db->fetchAllAssociative($sql);        // Line 54
    ↓
[Impact] Arbitrary SQL execution — full database compromise

Taint Flow (Validation Evidence)

Source: $request->request->getString('configuration')  (HTTP POST body, user-controlled)
    ↓  json_decode() → stdClass
[Store]  Persistent in database (custom_reports table)
[Load]   Config::getByName() → stdClass $config
    ↓  ✗ No sanitization (only bypassable regex blacklist)
[Sink]   $db->fetchAllAssociative($concatenatedSql)
    ↓
Impact: Attacker-controlled SQL executed against the database

Proof of Concept

Steps

  1. Authenticate as an admin user with reports_config permission
  2. Send a report update request with malicious SQL in the configuration:

Request

POST /admin/bundle/customreports/custom-report/update HTTP/1.1
Host: <target-host>
Content-Type: application/x-www-form-urlencoded
Cookie: PHPSESSID=<valid_admin_session>

name=malicious_report&configuration=%7B%22sql%22%3A%22SELECT%20id%2C%20username%2C%20password%20FROM%20users%22%2C%22from%22%3A%22users%22%2C%22where%22%3A%221%3D1%22%2C%22groupby%22%3A%22%22%2C%22dataSourceConfig%22%3A%7B%7D%7D
  1. Access the report data endpoint to retrieve extracted user credentials
  2. Alternatively, the where field can be set to:
    1=1 UNION SELECT TABLE_NAME, TABLE_SCHEMA, 1 FROM INFORMATION_SCHEMA.TABLES
    
    to enumerate all database tables

Expected Result

The custom report returns rows from arbitrary tables beyond what was intended, proving successful SQL injection.

Affected Component

  • File: bundles/CustomReportsBundle/src/Tool/Adapter/Sql.php
  • Method: buildQueryString() (lines 84-135), getBaseQuery() (lines 137-216), getData() (lines 25-58)
  • Class: Pimcore\Bundle\CustomReportsBundle\Tool\Adapter\Sql

Fix Recommendation

Replace the custom SQL concatenation approach with a parameterized query builder:

// Instead of:
$sql .= "\n" . $config['sql'];
$sql .= "\n" . $config['from'];
$sql .= "\n" . 'WHERE (' . $config['where'] . ')';

// Use a whitelist-based approach:
// 1. Only allow predefined table names from a whitelist
// 2. Use Doctrine QueryBuilder for WHERE conditions
// 3. Use parameterized queries for all user-supplied values
// 4. Cast LIMIT/OFFSET to integers

$sql .= ' LIMIT ' . (int)$offset . ',' . (int)$limit;

Resources

Affected Packages

3 total 3 fixed
EcosystemPackageVulnerable rangeFix
🐘Packagistpimcore/pimcore2026.1.0&&< 2026.1.62026.1.6
🐘Packagistpimcore/pimcore12.0.0-RC1&&< 12.3.1012.3.10
🐘Packagistpimcore/pimcoreall versions11.5.19

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for pimcore/pimcore. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update pimcore/pimcore to 2026.1.6 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-55416 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether CVE-2026-55416 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to CVE-2026-55416. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

# Security Advisory: SQL Injection in Custom Reports via Malicious Report Configuration ## Summary ### Impact A SQL injection vulnerability exists in the Custom Reports bundle (`bundles/CustomReportsBundle/src/Tool/Adapter/Sql.php:84-135`). An authenticated attacker with `reports_config` permission can inject arbitrary SQL via the report configuration fields (`sql`, `from`, `where`, `groupby`), which are directly concatenated into SQL queries without parameterization. The only protection is a regex blacklist that checks for `ALTER|CREATE|DROP|RENAME|TRUNCATE|UPDATE|DELETE` keywords, which i
O3 Security · Impact-Aware SCA

Is CVE-2026-55416 in your dependencies?

O3 detects CVE-2026-55416 across Packagist dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

CVE-2026-55416: pimcore/pimcore (High 8.8) | O3 Security