VYPR
High severity8.8GHSA Advisory· Published May 27, 2026· Updated May 27, 2026

Pimcore Admin Classic Bundle Vulnerable to SQL Injection in Translation Grid Date Filter via Unsanitized Property Parameter

CVE-2026-44741

Description

# GM-369

Summary

SQL injection in Pimcore's translation grid date filter — the user-supplied property field from the filter JSON is interpolated directly into a UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...))) SQL expression without parameterization or allowlist validation.

Affected

Component - Package: pimcore/admin-ui-classic-bundle - File: src/Controller/Admin/TranslationController.php - Lines: 565 (input), 569 (inadequate sanitization), 593 (injection point) - Endpoint: POST /admin/translation/translations

Description

The translation grid endpoint processes JSON filter parameters. When a filter has type: "date", the property field is extracted and used to construct a SQL expression:

$fieldname = $filter[$propertyField];              // Line 565 — user input
$fieldname = str_replace('--', '', $fieldname);    // Line 569 — trivially bypassable
$fieldname = $tableName . '.' . $fieldname;        // Line 577
$fieldname = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))";  // Line 593 — injection

The str_replace('--', '') sanitization is trivially bypassable (use /**/ comments or ----). In non-language mode, $fieldname is concatenated directly into the SQL condition without quoting or parameterization.

Impact

Authenticated user with translations view permission can extract arbitrary database data via UNION-based or error-based SQL injection. Combined with GM-249 (unsafe unserialize), this enables an SQLi → deserialization → RCE chain.

Proof of

Concept `` POST /admin/translation/translations filter=[{"property":"1))) UNION SELECT password FROM users WHERE ((1","type":"date","operator":"eq","value":"2026-01-01"}] ``

Suggested

Fix Validate $fieldname against an allowlist of valid column names before SQL interpolation: ``php $allowedDateColumns = ['creationDate', 'modificationDate']; if (!in_array($fieldname, $allowedDateColumns, true)) { continue; } ``

## References - CWE-89: SQL Injection - Related: CVE-2026-27461 (RLIKE injection in Dependency/Dao.php — different code path)

---

Suggested

Fix

In TranslationController.php: (1) Add allowlist check for non-language fieldnames before processing. (2) Replace raw string interpolation UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname}))) with $db->quoteIdentifier($fieldname) to prevent SQL injection in date filter expressions.

--- a/src/Controller/Admin/TranslationController.php
+++ b/src/Controller/Admin/TranslationController.php
@@ -569,7 +569,15 @@ class TranslationController extends AdminAbstractController
                 $fieldname = str_replace('--', '', $fieldname);
 
                 if (!$languageMode && in_array($fieldname, $validLanguages)
                     || $languageMode && !in_array($fieldname, $validLanguages)) {
                     continue;
                 }
 
+                // Allowlist non-language fieldnames to prevent SQL injection
+                $allowedNonLanguageFields = ['key', 'type', 'creationDate', 'modificationDate'];
+                if (!$languageMode && !in_array($fieldname, $allowedNonLanguageFields) && !in_array($fieldname, $validLanguages)) {
+                    continue;
+                }
+
                 if (!$languageMode) {
                     $fieldname = $tableName . '.' . $fieldname;
                 }
@@ -582,7 +590,7 @@ class TranslationController extends AdminAbstractController
                         } elseif ($filter[$operatorField] == 'eq') {
                             $operator = '=';
-                            $fieldname = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))";
+                            // Use validated fieldname only — never interpolate raw user input into SQL functions
+                            $fieldname = sprintf('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(%s)))', $db->quoteIdentifier($fieldname));
                         }

---

Proposed

Fix

--- a/src/Controller/Admin/TranslationController.php
+++ b/src/Controller/Admin/TranslationController.php
@@ -569,7 +569,15 @@ class TranslationController extends AdminAbstractController
                 $fieldname = str_replace('--', '', $fieldname);
 
                 if (!$languageMode && in_array($fieldname, $validLanguages)
                     || $languageMode && !in_array($fieldname, $validLanguages)) {
                     continue;
                 }
 
+                // Allowlist non-language fieldnames to prevent SQL injection
+                $allowedNonLanguageFields = ['key', 'type', 'creationDate', 'modificationDate'];
+                if (!$languageMode && !in_array($fieldname, $allowedNonLanguageFields) && !in_array($fieldname, $validLanguages)) {
+                    continue;
+                }
+
                 if (!$languageMode) {
                     $fieldname = $tableName . '.' . $fieldname;
                 }
@@ -582,7 +590,7 @@ class TranslationController extends AdminAbstractController
                         } elseif ($filter[$operatorField] == 'eq') {
                             $operator = '=';
-                            $fieldname = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))";
+                            // Use validated fieldname only — never interpolate raw user input into SQL functions
+                            $fieldname = sprintf('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(%s)))', $db->quoteIdentifier($fieldname));
                         }

Happy to submit this as a PR against a private fork if that is the preferred workflow.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

SQL injection in Pimcore's translation grid date filter allows authenticated users to extract database data via unsanitized property parameter.

Vulnerability

The SQL injection vulnerability resides in the pimcore/admin-ui-classic-bundle package, specifically in TranslationController.php at lines 565–593 [1][2]. The POST /admin/translation/translations endpoint processes JSON filter parameters. When a filter has "type": "date", the property field from user input is extracted and used to construct a SQL expression: UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname}))). The only sanitization is str_replace('--', '', $fieldname), which is trivially bypassable using SQL comments like /**/ or multiple dashes. All versions prior to 2.3.6 are affected [3].

Exploitation

An attacker needs an authenticated session with the translations view permission. They send a POST request to the endpoint with a crafted filter JSON where the property value breaks out of the SQL expression. For example: "property":"1))) UNION SELECT password FROM users WHERE ((1". The str_replace('--', '') bypass allows the injection to succeed, enabling UNION-based or error-based SQL injection [1][2].

Impact

Successful exploitation allows the attacker to extract arbitrary data from the database. Combined with another vulnerability (GM-249, unsafe unserialize), this SQL injection can be chained into a deserialization attack leading to remote code execution [1][2][4].

Mitigation

The fix validates $fieldname against an allowlist of allowed date columns (e.g., creationDate, modificationDate) before SQL interpolation [1][2]. The fix is included in release v2.3.6 of pimcore/admin-ui-classic-bundle [3]. Users should upgrade to this version immediately. No workaround is available.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
80e57a23d9e1

[Security]: Update unserialize to use allowed_classes option in Dashboard (#1111)

1 file changed · +6 3
  • src/Helper/Dashboard.php+6 3 modified
    @@ -58,9 +58,12 @@ protected function loadFile(): ?array
     
             if (empty($this->dashboards)) {
                 if (is_file($this->getConfigFile())) {
    -                $dashboards = Serialize::unserialize(file_get_contents($this->getConfigFile()));
    -                if (!empty($dashboards)) {
    -                    $this->dashboards = $dashboards;
    +                $dashboardFile = file_get_contents($this->getConfigFile());
    +                if ($dashboardFile !== false) {
    +                    $dashboards = unserialize($dashboardFile, ['allowed_classes' => false]);
    +                    if (is_array($dashboards) && !empty($dashboards)) {
    +                        $this->dashboards = $dashboards;
    +                    }
                     }
                 }
     
    

Vulnerability mechanics

Root cause

"Missing input validation and allowlist enforcement on the `property` field of date-type JSON filters allows direct SQL interpolation."

Attack vector

An attacker must be an authenticated user with the "translations view" permission [ref_id=1][ref_id=2]. The attacker sends a POST request to `/admin/translation/translations` with a JSON `filter` array containing a date-type filter object [ref_id=1]. The `property` field of that filter is extracted at line 565 and, after a trivially bypassable `str_replace('--', '')` sanitization (bypassable with `/**/` comments or `----`), is concatenated directly into a SQL expression without parameterization or allowlist validation [ref_id=1][ref_id=2]. This allows UNION-based or error-based SQL injection to extract arbitrary database data [ref_id=1][CWE-89].

Affected code

The vulnerability resides in `src/Controller/Admin/TranslationController.php` at the `POST /admin/translation/translations` endpoint [ref_id=1]. Lines 565 (user input extraction), 569 (inadequate sanitization via `str_replace('--', '')`), and 593 (injection point where `$fieldname` is interpolated into `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))`) are the affected code paths [ref_id=1][ref_id=2].

What the fix does

The advisory's suggested fix (no official patch is published in the bundle) adds an allowlist check for non-language fieldnames — only `key`, `type`, `creationDate`, and `modificationDate` are permitted — and replaces the raw string interpolation with `$db->quoteIdentifier($fieldname)` inside the `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` expression [ref_id=1][ref_id=2]. The allowlist prevents arbitrary column names from reaching the SQL query, and `quoteIdentifier()` safely quotes the identifier, eliminating injection [ref_id=1].

Preconditions

  • authAttacker must be authenticated with the 'translations view' permission
  • networkAttacker must be able to send POST requests to /admin/translation/translations
  • inputAttacker supplies a JSON filter array with a date-type filter containing a malicious 'property' field

Reproduction

Send a POST request to `/admin/translation/translations` with the following JSON body (as shown in the advisory) [ref_id=1][ref_id=2]:

``` filter=[{"property":"1))) UNION SELECT password FROM users WHERE ((1","type":"date","operator":"eq","value":"2026-01-01"}] ```

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.