Mermaid: Improper sanitization of `classDefs` in diagrams leads to CSS injection
GHSA-xcj9-5m2h-648r · CVE-2026-41148
Published · Modified
Description
Details
The state diagram and any other diagram type that routes user-controlled style strings through createCssStyles parser for Mermaid v11.14.0 and earlier captures classDef values with an unrestricted regex:
// packages/mermaid/src/diagrams/state/parser/stateDiagram.jison:83
<CLASSDEFID>[^\n]* { this.popState(); return 'CLASSDEF_STYLEOPTS' }
The value passes unsanitized through addStyleClass() -> createCssStyles() -> style.innerHTML (mermaidAPI.ts:418). A } in the value closes the generated CSS selector, and everything after becomes a new CSS rule on the page.
PoC
stateDiagram-v2
classDef x }*{ background-image: url("http://media.giphy.com/media/SggILpMXO7Xt6/giphy.gif")}
Patches
This has been patched in:
- v11.15.0 (see e9b0f34d8d82a6260077764ee45e1d7d90957a0f)
- v10.9.6 (see 8fead23c59166b7bab6a39eac81acebee2859102)
Workarounds
Setting "securityLevel": "sandbox" will prevent this, by rendering the mermaid diagram in a sandboxed <iframe>.
Impact
Enables page defacement, user tracking via url() callbacks, and DOM attribute exfiltration via CSS :has() selectors.
References
- WEB https://github.com/mermaid-js/mermaid/security/advisories/GHSA-xcj9-5m2h-648r
- ADVISORY https://nvd.nist.gov/vuln/detail/CVE-2026-41148
- WEB https://github.com/mermaid-js/mermaid/commit/8fead23c59166b7bab6a39eac81acebee2859102
- WEB https://github.com/mermaid-js/mermaid/commit/e9b0f34d8d82a6260077764ee45e1d7d90957a0f
- PACKAGE https://github.com/mermaid-js/mermaid
- WEB https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.15.0
- WEB https://github.com/mermaid-js/mermaid/releases/tag/v10.9.6
- WEB https://mermaid.js.org/config/schema-docs/config.html#securitylevel
Ready to move
Start Securing
Free, no credit card | First findings in minutes