Skip to content

Pimcore Studio: five coordinated flaws (Aug 28, 2026) — DataObject field-name RCE (CVE-2026-55634, 9.9), Hotspotimage PHP object injection (CVE-2026-55220), and a three-item privilege-escalation / SQLi / account-takeover set

Summary

On August 28, 2026, a coordinated batch of five GitHub Security Advisories landed against Pimcore, the open-source PHP/Doctrine digital-asset-management and e-commerce framework. The batch is dominated by two Critical items — a DataObject class-definition field-name RCE and a Hotspotimage PHP object-injection primitive — plus three High items (class-definition creation privilege escalation, DateFilter SQL injection, and password-reset-URL account takeover). All five are fixed in the same coordinated release train: Pimcore 2026.1.6 (12.x branch), 12.3.10, and the Studio backend-bundle backport 2025.4.6. No in-the-wild exploitation, actor, or infrastructure is named in any of the five advisories; they are researcher-disclosed, with two (the RCE sink and the object-injection gadget chain) confirmed against a locally deployed Pimcore.

The recurring theme is the Pimcore Studio / DataObject code-generation and object-store boundary: attacker-controllable identifiers and serialized metadata flow into generated PHP and into Serialize::unserialize() with no identifier allowlist or class allowlist. That is a durable audit pattern — any value that reaches codegen or deserialization without an allowlist is an injection primitive — and applies well beyond this specific release.

Advisory Product / component Class Severity Fix
GHSA-9x44-4gxf-8c25 / CVE-2026-55634 Pimcore DataObject class-definition field name RCE (PHP codegen injection) + secondary ALTER TABLE SQLi Critical (9.9, AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) 2026.1.6 / 12.3.10
GHSA-w23p-wrp7-ch38 / CVE-2026-55220 Pimcore Hotspotimage::getDataFromResource() PHP object injection (CWE-502) — unrestricted Serialize::unserialize over an object-store column Critical (no CVSS published) 2026.1.6 / 12.3.10
GHSA-f97c-ph8j-8vff / CVE-2026-55212 Pimcore Studio — class-definition creation endpoint Privilege escalation (insufficient authorization) High (7.1, AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N) 2026.1.6 / 2025.4.6
GHSA-79cw-hfcc-7mw9 / CVE-2026-55208 Pimcore Studio — DateFilter column key SQL injection (time-based blind, columnFilters array) High (7.7, AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N) 2026.1.6 / 2025.4.6
GHSA-h854-c3m3-mh5v / CVE-2026-55207 Pimcore — password-reset URL injection Account takeover + 2FA bypass High (8.8, AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H) 2026.1.6 / 2025.4.6

No exploitation, actor, infrastructure, or payload detail is named in any of the five advisories.

Tags

CVE-2026-55634 — DataObject class-definition field-name RCE (Critical, 9.9)

A DataObject class-definition field name is concatenated, without an identifier allowlist, into the PHP class source Pimcore generates for every DataObject class (protected $<fieldName>;). A user holding only the ordinary objects (DataObjects) permission — the standard permission for content editors who work with DataObjects, not an administrator or a dedicated "classes" permission — can import a class definition whose field name closes the property and injects arbitrary PHP into the generated class file, achieving remote code execution.

Mechanism: the field name is assembled into the class body in lib/DataObject/ClassBuilder/ClassBuilder.php (class <Name> extends … { + properties) and written to var/classes/DataObject/<Class>.php, which is autoloaded/included. A crafted field name such as pwn; public function __construct(){ … shell_exec("id"); } private $z escapes the property literal. The same unvalidated field name is also concatenated into ALTER TABLE DDL (ADD COLUMN / ADD INDEX), giving a parallel SQL-injection primitive.

Confidence: the RCE sink — the builder emitting attacker PHP into the generated class body and the __construct() executing a shell command — is runtime-confirmed in an isolated harness. The end-to-end live chain (Studio import path preserving the field name, the DDL step not aborting the save, and Pimcore instantiating the object so __construct() fires) is reasoned from source but not run end-to-end on a live Pimcore. Treat it as sink-confirmed + chain-reasoned, not a fully-executed live exploit.

Why it is 9.9: the injected PHP runs with the privileges of the PHP runtime (typically the web-server user) and reaches the OS — beyond the authority of the Pimcore application account the attacker started from — so scope is S:C. A reviewer scoring within the single PHP/OS authority (S:U) lands at 8.8 High; the severity floor is High regardless of the scope interpretation. It is a sibling / incomplete-coverage of the earlier DataObject composite-index SQL injection (CVE-2026-5394 / GHSA-r2f4-ff2p-xc64), whose fix hardened only CompositeIndexTrait and left the field-name path untouched. A secondary codegen-injection point (Service.php string-literal public const FIELD_… = '<name>';) is closed by the same allowlist.

CVE-2026-55220 — Hotspotimage PHP object injection (Critical, CWE-502)

Hotspotimage::getDataFromResource() calls Serialize::unserialize() with no class allowlist over the <field>__hotspots object-store column. On save, hotspot/marker/crop metadata is stored as Serialize::serialize($metaData) into that column — i.e. PHP serialized bytes, not JSON. The load path (essentially every object retrieval for objects whose class declares a Hotspotimage field with a non-null <field>__image) deserializes it with no allowlist, so any crafted serialized bytes an attacker can write into the column are directly executable.

Confirmed end-to-end against a real, locally deployed Pimcore v2026.1.4 (Composer skeleton + MariaDB + pimcore:install): the gadget is phpggc Guzzle/FW1 built against Pimcore's bundled guzzlehttp/guzzle 7.11.0; its GuzzleHttp\Cookie\FileCookieJar::__destruct writes an attacker-controlled file. The durable primitive is the store-write + no-allowlist-deserialize pairing.

Affected: all currently maintained releases, including the latest v2026.1.4 and v12.3.8 (verified against deployed v2026.1.4). The fix flips the deserialization default to allowed_classes=false (or a tight allowlist such as [MarkerHotspotItem::class]).

CVE-2026-55212 / -55208 / -55207 — privesc, SQLi, account takeover (High)

  • CVE-2026-55212 (GHSA-f97c-ph8j-8vff, High, 7.1) — insufficient authorization on the class-definition creation endpoint allows privilege escalation (Pimcore 2026.1.x with the Studio API enabled).
  • CVE-2026-55208 (GHSA-79cw-hfcc-7mw9, High, 7.7) — SQL injection via the column name in DateFilter: the POST /pimcore-studio/api/website-settings endpoint (and 11 other listing endpoints) accepts a columnFilters array where the column key is manually backtick-wrapped but injected into the query; the fixed named parameters mean PDO accepts the binding regardless of column content, enabling a time-based blind extraction of arbitrary data including admin password hashes. EqualsFilter / LikeFilter are not affected (they reuse the column name as a PDO named parameter, so injection characters break parameter binding).
  • CVE-2026-55207 (GHSA-h854-c3m3-mh5v, High, 8.8) — account takeover via password-reset URL injection lets an unauthenticated attacker hijack any admin account with a 2FA bypass.

Defender priorities

  1. Upgrade every Pimcore instance to the coordinated release: 2026.1.6 (12.x / current branch), 12.3.10, and the Studio backend-bundle backport 2025.4.6. The two Critical items are the priority; the RCE and the object-injection primitive both reach code execution from an authenticated or store-write primitive.
  2. Inventory DataObject field names and Hotspotimage fields. If you cannot patch immediately, hunt for the RCE shape (a DataObject class whose generated var/classes/DataObject/<Class>.php contains shell/constructor code) and for the <field>__hotspots object-store column containing attacker-controlled serialized bytes. The pre-patch detection/mitigation is the same as the field-name allowlist the patch adds.
  3. Treat as unattributed. None of the five names an actor, infrastructure, payload, or in-the-wild exploitation. Correlate to your exposure model rather than assuming a campaign; the durable pattern is identifier / serialized-metadata → codegen / deserialization without an allowlist, which is worth auditing in any similar PHP object-store or CMS-codegen product.
  4. Watch for exploitation telemetry on the two Critical items and for CVE backfill / NVD scoring of CVE-2026-55220 (no CVSS published at capture).

Assessment limits

  • CVE-2026-55634 is a sink-confirmed + chain-reasoned RCE (runtime-confirmed sink, live end-to-end not yet demonstrated); the advisory itself states this. The 9.9 score reflects S:C; the High floor holds under S:U.
  • CVE-2026-55220 carries no CVSS vector / score at publication; severity is the advisory's "critical." The gadget chain is confirmed against bundled guzzlehttp/guzzle 7.11.0.
  • The three High items have published CVSS vectors; the account-takeover item (8.8) is the most direct unauthenticated-adjacent win (requires user interaction / a valid reset flow).
  • Affected-version ranges for the four Studio/backend-bundle items are given as the fixed releases (2026.1.6 / 2025.4.6); the underlying Studio API surface is the Pimcore 2026.1.x / 12.x branch.

Sources