Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessCraft style element with onerror payload
-
DeliverySubmit to app using IN_PLACE sanitize
-
ExploitBypass neutralization via surviving rawtext text
-
ExecutionApp serializes and re-parses returned node
-
ImpactExecute script in victim browser
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Output encoding, context-aware escaping
MITRE ATT&CK
2 techniques across 2 tactics: Initial Access, Execution The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires the target application to call DOMPurify.sanitize(node, { IN_PLACE: true }) on a Node input (not a string) using a vulnerable version <=3.4.15, and to subsequently serialize the returned node and re-parse that serialized HTML in a plain HTML context - the published PoC runs with SAFE_FOR_XML at its default (true). The specific trigger is a rawtext element (e.g. <style>) whose text content carries markup (a closing </style> tag plus an img onerror payload); the 3.4.9 _forceRemove TypeError guard and _neutralizeSubtree attribute-stripping do not touch text content, so the killed node is returned with live markup. LIMITING FACTORS: this is not a default DOMPurify usage pattern - string inputs and non-IN_PLACE sanitization return an empty/safe result, so applications not using IN_PLACE mode with node inputs and a serialize-then-reparse round-trip are not affected. CVSS UI:A also indicates active victim interaction is part of the attack path. |
| Impact | CVSS 4.0 base score is 5.1 (medium): AV:N/AC:L/AT:N/PR:N/UI:A with no impact on the vulnerable system (VC:N/VI:N/VA:N) and low confidentiality/integrity impact on a subsequent system (SC:L/SI:L) - i.e. a classic client-side XSS whose damage lands in the victim's browser session rather than on the DOMPurify host. No EPSS score, SSVC decision, or CISA KEV status was provided in the input, so there is no quantitative exploitation-probability or automatability signal to weigh; absence of KEV means there is no evidence of active exploitation. However, the GHSA advisory ships a complete, independently-reproduced proof-of-concept (jsdom 30.0.1/29.1.1, Node 20.x/26.x), so working exploit code is effectively public. The signals are internally consistent - network vector with required user interaction matches a reflected/stored XSS - but exploitability is heavily gated by a non-default integration pattern (the target application must call DOMPurify.sanitize with IN_PLACE:true on a Node input and then serialize and re-parse the returned node), which is not captured by the CVSS metrics and materially lowers real-world reach. Net: a real but conditional XSS bug in a very widely used library; prioritize for applications known to use IN_PLACE mode, treat as lower urgency elsewhere. No EPSS/KEV data available - risk ranking relies on CVSS and confirmed PoC only. |
| Exploit ScenarioDerived | An attacker submits user-controlled content containing a <style> element whose text is '</style><img src=x onerror=...>' to a web application that sanitizes nodes with DOMPurify.sanitize(node, { IN_PLACE: true }). DOMPurify force-removes the rawtext root but returns it with its text payload intact; when the application serializes the returned node and re-parses the HTML, the img onerror handler executes script in the victim's browser. A working proof-of-concept is published in the GHSA advisory. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 12, 2026
Cross-site scripting in DOMPurify 3.4.15 and earlier lets an attacker smuggle live markup through the library's IN_PLACE sanitization path when a rawtext element such as <style> is passed as a DOM Node: the killed node is returned detached but its text content still contains the closing </style> tag plus an img onerror payload, which materializes as script if the application serializes that node and re-parses the resulting HTML in a plain HTML context. Only applications that call DOMPurify.sanitize(node, { IN_PLACE: true }) with a Node (not a string) and then perform a serialize-then-reparse round-trip on the returned value are affected; the CVSS 4.0 base score is 5.1 (medium, AV:N/AC:L/PR:N/UI:A, no impact to the vulnerable system, low confidentiality and integrity impact on a subsequent system), and a working proof-of-concept is published in the upstream advisory, though there is no indication of confirmed active exploitation. Vendor-released patch: 3.4.16.
RemediationAI
Upgrade the dompurify npm dependency to 3.4.16 or later, the vendor-released patch version; the fix is delivered by pull request https://github.com/cure53/DOMPurify/pull/1636 (commit b9b9d80f7e401771c2ccaef5f45def7eec8f27d7) and the change is documented in GHSA-6688-9rhm-gjv2 at https://github.com/cure53/DOMPurify/security/advisories/GHSA-6688-9rhm-gjv2. If an immediate upgrade is not possible, the highest-fidelity compensating control is to stop passing DOM Nodes to DOMPurify with IN_PLACE: true and instead sanitize the input as a string (or use non-IN_PLACE output such as RETURN_DOM/RETURN_DOM_FRAGMENT and insert the returned tree directly), since string and default-mode sanitization return an empty/safe result for this payload - the trade-off is that code depending on in-place mutation of a caller-owned node must be refactored, and any caller that keeps the untrusted node reference must be audited. Because the bypass only materializes when the returned node is serialized (outerHTML) and re-parsed as HTML, breaking the serialize-then-reparse round-trip on sanitizer output - for example by consuming the returned node directly in the DOM rather than round-tripping its markup through innerHTML or a template renderer - removes the execution primitive; this is a containment measure, not a substitute for upgrading, and it leaves the unsanitized rawtext content reachable to any other code path that does serialize the node. As defense in depth, keep a strict Content-Security-Policy (script-src without unsafe-inline and without unsafe-eval) to blunt the img onerror execution primitive, and re-sanitize any sanitizer output that is persisted and later re-parsed. Note that no backport for releases earlier than 3.4.16 is identified, so pinned or vendored copies of DOMPurify must be updated explicitly.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in npm
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
DOMPurify is a widely used client-side HTML/SVG/MathML sanitizer from Cure53, distributed on npm as dompurify (CPE cpe:2.3:a:cure53:dompurify:*:*:*:*:*:*:*:*), typically wrapping a DOM implementation such as the native browser DOM or jsdom. IN_PLACE mode is a non-default Node-input path in which sanitization mutates and returns the caller's own node rather than a sanitized string. The root cause is CWE-79 (improper neutralization of input during web page generation, i.e. cross-site scripting) combined with an incomplete fix: the 3.4.9 hardening for the IN_PLACE detached-root class added a fail-closed TypeError in _forceRemove when a node selected for removal cannot be detached, plus a _neutralizeSubtree pass that strips non-allowlisted attributes from removed subtrees. Both defenses address attributes and detachment failure only. When the force-removed root is a rawtext element such as <style>, the payload lives in the element's text content, so the TypeError guard is never reached (the node detaches cleanly), _neutralizeSubtree strips nothing (there are no attributes to strip), and the IN_PLACE exit returns the detached, never-sanitized <style> whose text still carries '</style><img src=x onerror=1>'. Because the HTML parser treats <style> as a rawtext state element, that text is inert while embedded, but serializing the node with outerHTML re-emits the raw text and re-parsing it in ordinary HTML context closes the style element and instantiates the injected <img> element with its onerror handler - a classic sanitizer round-trip bypass requiring no foreign-content context. The same Node sanitized without IN_PLACE returns an empty result, which confirms the defect is specific to the IN_PLACE return path handing back the killed node. The affected version range is <= 3.4.15 across all npm distribution channels, and SAFE_FOR_XML at its default (true) does not prevent the issue.
Know when Dompurify gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N
Network-delivered XSS executing in the victim browser (scope change S:C, UI:R); no attacker privileges (PR:N); low confidentiality/integrity impact on the subsequent context and no availability impact.
Primary rating from Vendor (VulnCheck).
CVSS VectorVendor: VulnCheck
Lifecycle Timeline
2DescriptionCVE.org
DOMPurify before 3.4.16 contains a cross-site scripting vulnerability that allows attackers to bypass sanitization because IN_PLACE mode returns a force-removed style element whose text content still carries markup. Attackers can supply a style element containing a closing style tag and an img onerror payload, which executes script when the application serializes and re-parses the returned node.
Blast Radius
ecosystem impact- 231 npm packages depend on dompurify (63 direct, 169 indirect)
Ecosystem-wide dependent count for version 3.4.16.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.
DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. Rated medium severity (CVSS 6
Cure53 DOMPurify before 2.0.17 allows mutation XSS. Rated medium severity (CVSS 6.1), this vulnerability is remotely exp
DOMPurify before 2.0.1 allows XSS because of innerHTML mutation XSS (mXSS) for an SVG element or a MATH element, as demo
DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. Rated critical severity (CVSS
Mutation-XSS in DOMPurify before 3.3.2 enables JavaScript execution in victim browsers when sanitized output is re-inser
Hook mutation pollution in DOMPurify <= 3.4.5 allows persistent bypass of HTML sanitization defaults when application-in
Trusted Types policy state contamination in DOMPurify 3.0.0-3.4.8 allows a previously supplied TRUSTED_TYPES_POLICY to s
Prototype pollution in DOMPurify's USE_PROFILES mode enables DOM-based XSS by causing the sanitizer to accept event hand
URI validation bypass in DOMPurify 3.3.1 and earlier allows `javascript:` protocol payloads to survive HTML sanitization
SAFE_FOR_TEMPLATES bypass in DOMPurify 3.0.0-3.4.7 allows template expressions such as ${evil}, {{evil}}, and <%evil%> t
Cross-site scripting in DOMPurify 3.4.6 and earlier enables script execution when the library's IN_PLACE sanitization mo
Stored XSS is achievable in applications using DOMPurify's setConfig() API combined with an uponSanitizeAttribute hook t
EUVD-2026-97647
GHSA-cjhx-p48c-gfm9
NVD
CVE.org
EPSS
Exploit-DB