Every CVE Search/ Get API key

CVE-2026-55220

Pimcore Hotspotimage getDataFromResource() unrestricted Serialize::unserialize over object-store column

9.3 CriticalFix available

Pimcore is an Open Source Data & Experience Management Platform. Prior to 11.5.19, 12.3.10, and 2026.1.6, Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() in models/DataObject/ClassDefinition/Data/Hotspotimage.php passes the field __hotspots object-store column to Pimcore\Tool\Serialize::unserialize() without an allowed-classes restriction after JSON decoding fails. An attacker with a separate capability to write crafted PHP serialized bytes into that column can instantiate available classes and trigger magic methods when an affected DataObject is loaded, which can produce arbitrary file writes or code execution through bundled gadget chains. The related ImageGallery, Block, and Video callers use the same fallback pattern, but the identified June fix changes the Hotspotimage caller only. This issue is fixed for Hotspotimage in versions 11.5.19, 12.3.10, and 2026.1.6.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.68%Up 0.2 points since Aug 29, 2026
90%50%10%1%

What each source reports

CVE List Score used 9.3

Pimcore Hotspotimage getDataFromResource() unrestricted Serialize::unserialize over object-store column

Pimcore is an Open Source Data & Experience Management Platform. Prior to 11.5.19, 12.3.10, and 2026.1.6, Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() in models/DataObject/ClassDefinition/Data/Hotspotimage.php passes the field __hotspots object-store column to Pimcore\Tool\Serialize::unserialize() without an allowed-classes restriction after JSON decoding fails. An attacker with a separate capability to write crafted PHP serialized bytes into that column can instantiate available classes and trigger magic methods when an affected DataObject is loaded, which can produce arbitrary file writes or code execution through bundled gadget chains. The related ImageGallery, Block, and Video callers use the same fallback pattern, but the identified June fix changes the Hotspotimage caller only. This issue is fixed for Hotspotimage in versions 11.5.19, 12.3.10, and 2026.1.6.

Record
CVE-2026-55220
CVSS 4.0
9.3 CriticalCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-502
Updated
2026-11-02
EUVDEUVD-2026-67870 9.3

Pimcore is an Open Source Data & Experience Management Platform. Prior to 11.5.19, 12.3.10, and 2026.1.6, Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() in models/DataObject/ClassDefinition/Data/Hotspotimage.php passes the field __hotspots object-store column to Pimcore\Tool\Serialize::unserialize() without an allowed-classes restriction after JSON decoding fails. An attacker with a separate capability to write crafted PHP serialized bytes into that column can instantiate available classes and trigger magic methods when an affected DataObject is loaded, which can produce arbitrary file writes or code execution through bundled gadget chains. The related ImageGallery, Block, and Video callers use the same fallback pattern, but the identified June fix changes the Hotspotimage caller only. This issue is fixed for Hotspotimage in versions 11.5.19, 12.3.10, and 2026.1.6.

Record
EUVD-2026-67870
CVSS 4.0
9.3 CriticalCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-w23p-wrp7-ch38 9.3

Pimcore Hotspotimage getDataFromResource() unrestricted Serialize::unserialize over object-store column (PHP Object Injection, CWE-502)

Summary

Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() deserializes the *__hotspots object-store column through the Pimcore\Tool\Serialize::unserialize() wrapper without a class allowlist (the wrapper's $allowedClasses parameter defaults to true, i.e. fully unrestricted). Because the persistence layer always stores this column as PHP-serialize()d bytes, every load of a DataObject that has a Hotspotimage (advanced image) field runs an unrestricted unserialize() over the stored column value. An attacker who can write the *__hotspots store column with crafted serialized bytes achieves PHP Object Injection (CWE-502): arbitrary classes are instantiated and their magic methods (__wakeup/__destruct) execute, which is exploitable for remote code execution via gadget chains present in Pimcore's own bundled dependencies (e.g. guzzlehttp/guzzle).

The same field-data family also affects the sibling marshallers ImageGallery, Block, and Video, which use the identical json_decode(...) ?: Serialize::unserialize(...) fallback over their respective store columns. The root cause is shared: Serialize::unserialize() defaults to an unrestricted class list, and these callers pass no second argument.

Severity

High. Successful exploitation yields PHP Object Injection leading to remote code execution (proven below as arbitrary file write using a gadget from Pimcore's bundled guzzlehttp/guzzle 7.11.0). This is the deserialization leg of an attack: it requires the ability to write the *__hotspots object-store column with attacker-chosen serialized bytes. No class-allowlist defense is present, so any such write is directly weaponizable on the next object load. CVSS-wise this is comparable to other deserialization sinks over attacker-influenceable storage in this codebase.

Affected component

  • File: models/DataObject/ClassDefinition/Data/Hotspotimage.php, method getDataFromResource().
  • Vulnerable lines (v2026.1.4 / v12.3.8):
    $metaData = $data[$this->getName() . '__hotspots'];
    // check if the data is JSON (backward compatibility)
    $md = json_decode($metaData, true);
    if (!$md) {
        $md = Serialize::unserialize($metaData);   // unrestricted: allowed_classes defaults to true
    } elseif (is_array($md)) {
        $md['hotspots'] = $md;
    }
    
  • Root enabler: lib/Tool/Serialize.php
    public static function unserialize(?string $data = null, array|bool $allowedClasses = true): mixed
    {
        if ($data === null || $data === '') { return $data; }
        return unserialize($data, ['allowed_classes' => $allowedClasses]);  // default true = unrestricted
    }
    
  • Sibling marshallers with the identical fallback shape: ImageGallery, Block, Video (DataObject\ClassDefinition\Data).
  • Package: pimcore/pimcore (Composer).
  • Affected versions: all currently maintained releases, including the latest v2026.1.4 and v12.3.8 (verified against deployed v2026.1.4).

Data flow

  1. On save, Hotspotimage::getDataForResource() stores the hotspot/marker/crop metadata as Serialize::serialize($metaData) into the <field>__hotspots object-store column — i.e. PHP serialized bytes, not JSON.
  2. On load, Hotspotimage::getDataFromResource() reads that column, calls json_decode() (which fails for the serialized format), and therefore falls through to Serialize::unserialize($metaData) with the default unrestricted class list.
  3. Serialize::unserialize() invokes unserialize($data, ['allowed_classes' => true]), instantiating any class named in the bytes and triggering its magic methods.
  4. The load path is exercised on essentially every object retrieval (admin grid/detail, frontend rendering, Studio/API reads, inheritance walks) for objects whose class declares a Hotspotimage field, with a non-null <field>__image.

The attacker primitive is the ability to place crafted serialized bytes into the <field>__hotspots store column (for…

Record
GHSA-w23p-wrp7-ch38
CVSS 4.0
9.3 CriticalCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-502
Updated
2026-11-02
NVD 9.3

Pimcore is an Open Source Data & Experience Management Platform. Prior to 11.5.19, 12.3.10, and 2026.1.6, Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() in models/DataObject/ClassDefinition/Data/Hotspotimage.php passes the field __hotspots object-store column to Pimcore\Tool\Serialize::unserialize() without an allowed-classes restriction after JSON decoding fails. An attacker with a separate capability to write crafted PHP serialized bytes into that column can instantiate available classes and trigger magic methods when an affected DataObject is loaded, which can produce arbitrary file writes or code execution through bundled gadget chains. The related ImageGallery, Block, and Video callers use the same fallback pattern, but the identified June fix changes the Hotspotimage caller only. This issue is fixed for Hotspotimage in versions 11.5.19, 12.3.10, and 2026.1.6.

Record
CVE-2026-55220
CVSS 4.0
9.3 CriticalCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-502
Updated
2026-11-02
OSV 9.3

Pimcore Hotspotimage getDataFromResource() unrestricted Serialize::unserialize over object-store column

Pimcore is an Open Source Data & Experience Management Platform. Prior to 11.5.19, 12.3.10, and 2026.1.6, Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() in models/DataObject/ClassDefinition/Data/Hotspotimage.php passes the field __hotspots object-store column to Pimcore\Tool\Serialize::unserialize() without an allowed-classes restriction after JSON decoding fails. An attacker with a separate capability to write crafted PHP serialized bytes into that column can instantiate available classes and trigger magic methods when an affected DataObject is loaded, which can produce arbitrary file writes or code execution through bundled gadget chains. The related ImageGallery, Block, and Video callers use the same fallback pattern, but the identified June fix changes the Hotspotimage caller only. This issue is fixed for Hotspotimage in versions 11.5.19, 12.3.10, and 2026.1.6.

Record
CVE-2026-55220
CVSS 4.0
9.3 CriticalCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-502
Updated
2026-11-02
OSVGHSA-w23p-wrp7-ch38 9.3

Pimcore Hotspotimage getDataFromResource() unrestricted Serialize::unserialize over object-store column (PHP Object Injection, CWE-502)

Summary

Pimcore\Model\DataObject\ClassDefinition\Data\Hotspotimage::getDataFromResource() deserializes the *__hotspots object-store column through the Pimcore\Tool\Serialize::unserialize() wrapper without a class allowlist (the wrapper's $allowedClasses parameter defaults to true, i.e. fully unrestricted). Because the persistence layer always stores this column as PHP-serialize()d bytes, every load of a DataObject that has a Hotspotimage (advanced image) field runs an unrestricted unserialize() over the stored column value. An attacker who can write the *__hotspots store column with crafted serialized bytes achieves PHP Object Injection (CWE-502): arbitrary classes are instantiated and their magic methods (__wakeup/__destruct) execute, which is exploitable for remote code execution via gadget chains present in Pimcore's own bundled dependencies (e.g. guzzlehttp/guzzle).

The same field-data family also affects the sibling marshallers ImageGallery, Block, and Video, which use the identical json_decode(...) ?: Serialize::unserialize(...) fallback over their respective store columns. The root cause is shared: Serialize::unserialize() defaults to an unrestricted class list, and these callers pass no second argument.

Severity

High. Successful exploitation yields PHP Object Injection leading to remote code execution (proven below as arbitrary file write using a gadget from Pimcore's bundled guzzlehttp/guzzle 7.11.0). This is the deserialization leg of an attack: it requires the ability to write the *__hotspots object-store column with attacker-chosen serialized bytes. No class-allowlist defense is present, so any such write is directly weaponizable on the next object load. CVSS-wise this is comparable to other deserialization sinks over attacker-influenceable storage in this codebase.

Affected component

  • File: models/DataObject/ClassDefinition/Data/Hotspotimage.php, method getDataFromResource().
  • Vulnerable lines (v2026.1.4 / v12.3.8):
    $metaData = $data[$this->getName() . '__hotspots'];
    // check if the data is JSON (backward compatibility)
    $md = json_decode($metaData, true);
    if (!$md) {
        $md = Serialize::unserialize($metaData);   // unrestricted: allowed_classes defaults to true
    } elseif (is_array($md)) {
        $md['hotspots'] = $md;
    }
    
  • Root enabler: lib/Tool/Serialize.php
    public static function unserialize(?string $data = null, array|bool $allowedClasses = true): mixed
    {
        if ($data === null || $data === '') { return $data; }
        return unserialize($data, ['allowed_classes' => $allowedClasses]);  // default true = unrestricted
    }
    
  • Sibling marshallers with the identical fallback shape: ImageGallery, Block, Video (DataObject\ClassDefinition\Data).
  • Package: pimcore/pimcore (Composer).
  • Affected versions: all currently maintained releases, including the latest v2026.1.4 and v12.3.8 (verified against deployed v2026.1.4).

Data flow

  1. On save, Hotspotimage::getDataForResource() stores the hotspot/marker/crop metadata as Serialize::serialize($metaData) into the <field>__hotspots object-store column — i.e. PHP serialized bytes, not JSON.
  2. On load, Hotspotimage::getDataFromResource() reads that column, calls json_decode() (which fails for the serialized format), and therefore falls through to Serialize::unserialize($metaData) with the default unrestricted class list.
  3. Serialize::unserialize() invokes unserialize($data, ['allowed_classes' => true]), instantiating any class named in the bytes and triggering its magic methods.
  4. The load path is exercised on essentially every object retrieval (admin grid/detail, frontend rendering, Studio/API reads, inheritance walks) for objects whose class declares a Hotspotimage field, with a non-null <field>__image.

The attacker primitive is the ability to place crafted serialized bytes into the <field>__hotspots store column (for…

Record
GHSA-w23p-wrp7-ch38
CVSS 4.0
9.3 CriticalCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-502
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
pimcore/pimcore
Packagist
2026.1.0 to 2026.1.5
2026.1.6
pimcore/pimcore
Packagist
through 12.3.9
12.3.10
pimcore/pimcore
Packagist
2026.1.0 up to 2026.1.6, plus listed versions
v2026.1.0v2026.1.1v2026.1.2v2026.1.3v2026.1.4v2026.1.5
2026.1.6
pimcore/pimcore
Packagist
before 12.3.10, plus listed versions
10.0.82.2.02.2.12.2.22.3.0
Show 45 moreShow less
3.0.03.0.13.0.23.0.33.0.43.0.53.0.63.1.03.1.14.0.04.0.14.1.04.1.14.1.24.1.34.2.04.3.04.3.14.4.04.4.14.4.24.4.34.5.04.6.04.6.14.6.24.6.34.6.44.6.5v10.0.0v10.0.0-BETA1v10.0.0-BETA2v10.0.0-BETA3v10.0.0-BETA4v10.0.1v10.0.2v10.0.3v10.0.4v10.0.5v10.0.6v10.0.7v10.0.9v10.1.0v10.1.1v10.1.2
12.3.10

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55220 is a critical vulnerability (CVSS 9.3) in Pimcore, published August 28, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.68%, the 52nd percentile. Fixed in pimcore/pimcore 2026.1.6.

References

This page doesn't list everything

Left out here: 275 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open