PT-2026-43629 · Packagist · Pimcore Admin Classic Bundle

Published

2026-05-27

·

Updated

2026-05-27

·

CVE-2026-44741

CVSS v3.1

8.8

High

VectorAV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

GitHub Security Advisory Draft — 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:
$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.

Fix

SQL injection

Weakness Enumeration

Related Identifiers

CVE-2026-44741
GHSA-H4PH-CRVJ-9H92

Affected Products

Pimcore Admin Classic Bundle