Pimcore Platform v12.3.3 - Stored XSS in Document Editable Embed rendering

4.8

Medium

Detected by

Fluid Attacks AI SAST Scanner

Disclosed by

Oscar Naveda

Summary

Full name

Pimcore Platform v12.3.3 - Stored XSS in Document Editable Embed rendering allowing JavaScript execution in published frontend pages

Code name

State

Public

Release date

Affected product

pimcore

Vendor

pimcore

Affected version(s)

v12.3.3

Vulnerability name

Stored cross-site scripting (XSS)

Remotely exploitable

Yes

CVSS v4.0 vector string

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N

CVSS v4.0 base score

4.8

Exploit available

Yes

CVE ID(s)

Description

An authenticated attacker with permission to edit document content can store crafted HTML/JavaScript in a Document embed editable and cause script execution when the published page is rendered.

The server-side sink is Pimcore\Model\Document\Editable\Embed::frontend(), which forwards the editable value to Embera->autoEmbed() and returns the result directly. Twig then renders pimcore_* editables as trusted HTML with no escaping.

Because Embera returns the original input text when no supported provider URL is embedded, arbitrary HTML such as <script> can pass through unchanged. A mixed payload containing a valid provider URL plus trailing HTML/JavaScript also remains executable because only the matched URL is replaced.

Vulnerability

Case A (validated by code-path and library runtime): HTML-only payload passthrough

  1. Source persistence: attacker-controlled url value is accepted from editmode input and stored in the editable state.

  2. Persistence/load path:

    • setDataFromEditmode() copies $data['url'] into $this->url.

    • setDataFromResource() restores $unserializedData['url'] from documents_editables.

  3. Sink:

    • Embed::frontend() calls Embera->autoEmbed($this->url) and returns $html directly.

  4. Rendering:

    • Twig registers pimcore_* as is_safe => ['html'], so the returned string is emitted without escaping.

  5. Impact:

    • If the stored value is <script>alert(1)</script>, Embera returns it unchanged, and the script executes in the victim's browser.

Case B (validated by library runtime): valid provider URL plus trailing script

  1. Attacker stores a payload such as:

    • https://www.youtube.com/watch?v=J---aiyznGQ <script>alert(1)</script>

  2. Embera->autoEmbed() replaces only the supported URL with provider HTML.

  3. Residual attacker-controlled HTML remains in the returned string.

  4. Result:

    • Frontend output contains a provider <iframe> followed by attacker-controlled <script>.

Case C (trust-boundary corroboration): no equivalent sanitizer in embed

  1. Pimcore treats editable output as HTML-capable by design.

  2. Wysiwyg explicitly sanitizes persisted HTML before saving.

  3. Embed has no corresponding URL validation, HTML sanitization, or output escaping step.

  4. This leaves the embed field as a direct content-to-HTML sink.

Relevant code:

  • models/Document/Editable/Embed.php:52-75

  • models/Document/Editable/Embed.php:92-103

  • lib/Twig/Extension/DocumentEditableExtension.php:39-45

  • lib/Templating/Renderer/EditableRenderer.php:71-73

  • models/Document/Editable/Wysiwyg.php:130-136

  • composer.json:68

Relevant dependency behavior:

  • Embera\Embera::autoEmbed() Returns the original text when no replacement occurs.

  • Embera provider matching is an allowlist, but it does not enforce that the input field is a pure URL string.

PoC

Application-level PoC

Precondition:

  • A page template renders an embed editable, for example:

{{ pimcore_embed("socialWidgets") }}
{{ pimcore_embed("socialWidgets") }}
{{ pimcore_embed("socialWidgets") }}
{{ pimcore_embed("socialWidgets") }}

Reproduction:

  1. Authenticate as a user with permission to edit/publish the target document.

  2. In document editmode, set the embed value to one of the following payloads.

HTML-only payload:

<script>alert("PIMCORE_EMBED_XSS")</script>
<script>alert("PIMCORE_EMBED_XSS")</script>
<script>alert("PIMCORE_EMBED_XSS")</script>
<script>alert("PIMCORE_EMBED_XSS")</script>

Mixed provider payload:

https://www.youtube.com/watch?v=J---aiyznGQ <script>alert("PIMCORE_EMBED_XSS")</script>
https://www.youtube.com/watch?v=J---aiyznGQ <script>alert("PIMCORE_EMBED_XSS")</script>
https://www.youtube.com/watch?v=J---aiyznGQ <script>alert("PIMCORE_EMBED_XSS")</script>
https://www.youtube.com/watch?v=J---aiyznGQ <script>alert("PIMCORE_EMBED_XSS")</script>
  1. Save and publish the document.

  2. Visit the frontend page containing the editable.

Expected result:

  • Browser executes alert("PIMCORE_EMBED_XSS").

Minimal dependency-level confirmation

The underlying dependency behavior can be reproduced with Embera 2.0.14:

$e = new Embera\Embera();
echo $e->autoEmbed('<script>alert(1)</script>');
echo $e->autoEmbed('https://www.youtube.com/watch?v=J---aiyznGQ <script>alert(1)</script>');
$e = new Embera\Embera();
echo $e->autoEmbed('<script>alert(1)</script>');
echo $e->autoEmbed('https://www.youtube.com/watch?v=J---aiyznGQ <script>alert(1)</script>');
$e = new Embera\Embera();
echo $e->autoEmbed('<script>alert(1)</script>');
echo $e->autoEmbed('https://www.youtube.com/watch?v=J---aiyznGQ <script>alert(1)</script>');
$e = new Embera\Embera();
echo $e->autoEmbed('<script>alert(1)</script>');
echo $e->autoEmbed('https://www.youtube.com/watch?v=J---aiyznGQ <script>alert(1)</script>');

Expected result:

  • First call returns <script>alert(1)</script> unchanged.

  • Second call returns an embedded YouTube iframe, followed by <script>alert(1)</script>.

Evidence of Exploitation

  • Video of exploitation.

  • Static evidence

Our security policy

We have reserved the ID CVE-2026-5362 to refer to this issue from now on.

Disclosure policy

System Information

Pimcore Platform
Version v12.3.3-62-g271a0a0b7b
Operating System: Any

References

Github Repository: https://github.com/pimcore/pimcore
Security: https://github.com/pimcore/pimcore/security

Mitigation

There is currently no patch available for this vulnerability.

Credits

The vulnerability was discovered by Oscar Naveda from Fluid Attacks' Offensive Team using the AI SAST Scanner.

Timeline

Vulnerability discovered

Vendor contacted

Public disclosure

Does your application use this vulnerable software?

During our free trial, our tools assess your application, identify vulnerabilities, and provide recommendations for their remediation.

Fluid Attacks' solutions enable organizations to identify, prioritize, and remediate vulnerabilities in their software throughout the SDLC. Supported by AI, automated tools, and pentesters, Fluid Attacks accelerates companies' risk exposure mitigation and strengthens their cybersecurity posture.

Get an AI summary of Fluid Attacks

Subscribe to our newsletter

Stay updated on our upcoming events and latest blog posts, advisories and other engaging resources.

© 2026 Fluid Attacks. We hack your software.

Fluid Attacks' solutions enable organizations to identify, prioritize, and remediate vulnerabilities in their software throughout the SDLC. Supported by AI, automated tools, and pentesters, Fluid Attacks accelerates companies' risk exposure mitigation and strengthens their cybersecurity posture.

Subscribe to our newsletter

Stay updated on our upcoming events and latest blog posts, advisories and other engaging resources.

Get an AI summary of Fluid Attacks

© 2026 Fluid Attacks. We hack your software.

Fluid Attacks' solutions enable organizations to identify, prioritize, and remediate vulnerabilities in their software throughout the SDLC. Supported by AI, automated tools, and pentesters, Fluid Attacks accelerates companies' risk exposure mitigation and strengthens their cybersecurity posture.

Subscribe to our newsletter

Stay updated on our upcoming events and latest blog posts, advisories and other engaging resources.

Get an AI summary of Fluid Attacks

© 2026 Fluid Attacks. We hack your software.