Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessSupply crafted markup with armed on* handlers
-
DeliveryEmbed handlers inside wrapper targeted by removing hook
-
ExploitafterSanitize hook detaches subtree without neutralization
-
ExecutionLive DOM retains armed event handler
-
ImpactHandler fires executing script in victim origin
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 victim application to invoke DOMPurify.sanitize(node, { IN_PLACE: true }) AND to register an afterSanitizeElements or afterSanitizeAttributes hook that removes a non-root element; only then does the detached subtree escape neutralization and retain armed on* handlers on the live DOM. This is a non-default, application-specific configuration - IN_PLACE mode and node-removing afterSanitize hooks are not DOMPurify defaults - which sharply limits the affected population despite the library's broad deployment. Further limiting factors: the attacker only supplies markup (no authentication needed, PR:N) but active victim interaction is required to render the content (UI:A), and impact is confined to script execution in the victim origin (DOM XSS), not host compromise. |
| Impact | This is a genuine but conditional, moderate-risk DOM XSS (CVSS 4.0 base 5.1, Medium) rather than a widespread critical. The vector AV:N/AC:L/AT:N/PR:N/UI:A indicates network-reachable, unauthenticated triggering but requires active victim interaction (UI:A) and yields only low confidentiality/integrity impact on a subsequent system (VC:N/VI:N/VA:N, SC:L/SI:L), consistent with script execution in the victim origin rather than full system compromise. The signals do NOT suggest urgent mass-exploitation: there is no CISA KEV listing, no EPSS score was supplied in the input, and no public proof-of-concept is referenced - so exploitation status is 'no public exploit identified at time of analysis.' The real limiter is configuration dependency: the flaw only manifests when an application calls DOMPurify.sanitize with IN_PLACE:true AND registers a node-removing afterSanitizeElements/afterSanitizeAttributes hook, which the CVSS base vector does not capture (base AT:N arguably understates this prerequisite). Note a signal nuance to verify: the 4.0 vector marks AT:N (no special attack requirement) and AC:L, yet the advisory describes a fairly narrow non-default configuration, so defenders should treat real-world attack complexity as higher than the base vector implies. Priority is elevated chiefly because DOMPurify is a very widely embedded sanitization library, so even a narrow config pattern can appear across many downstream applications. |
| Exploit ScenarioDerived | A victim web application sanitizes user-supplied HTML with DOMPurify in IN_PLACE mode and uses an afterSanitize hook that strips a wrapper element; an attacker submits markup placing on* handlers (e.g. an <img onerror=...>) inside that wrapper. When the hook removes the wrapper's root but the detached subtree is never neutralized, the queued event handler fires in the victim's origin after sanitize() returns, executing attacker script. No public exploit code is referenced, and the attack requires the victim app's specific IN_PLACE-plus-hook configuration plus user interaction (UI:A) to render the content. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 12, 2026
DOM-based cross-site scripting in DOMPurify 3.4.13 through 3.4.15 lets unauthenticated attackers who supply markup retain armed on* event handlers on a subtree that a sanitization hook removes, so a queued handler such as an img onerror fires in the victim origin after sanitize() returns. The flaw is conditional rather than universal: it only triggers when the host application calls DOMPurify.sanitize(node, { IN_PLACE: true }) and registers an afterSanitizeElements or afterSanitizeAttributes hook that removes a non-root element, a supported but non-default configuration, which sharply narrows the affected population despite DOMPurify's very broad deployment. Independent assessment rates it CVSS 3.1 AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N (attacker markup, victim interaction required, script execution confined to the victim origin rather than host compromise); no public exploit code identified at time of analysis.
RemediationAI
Vendor-released patch: upgrade the dompurify npm package to 3.4.16 (for example npm install dompurify@3.4.16), which resolves the issue; the change landed upstream via PR https://github.com/cure53/DOMPurify/pull/1636 and commit https://github.com/cure53/DOMPurify/commit/b9b9d80f7e401771c2ccaef5f45def7eec8f27d7, and details are in GHSA-p98j-92pf-mc4p (https://github.com/cure53/DOMPurify/security/advisories/GHSA-p98j-92pf-mc4p) with a VulnCheck advisory at https://www.vulncheck.com/advisories/dompurify-from-3.4.13-before-3.4.16-dom-xss-via-in-place-aftersanitize-hooks. Where the library cannot be upgraded immediately, the highest-value compensating control is to stop using IN_PLACE mode: sanitize an off-document or cloned node and insert the returned sanitized output instead, so the caller's live tree never holds subtrees that a hook detached; the trade-off is that IN_PLACE users must rework DOM insertion logic, since the return value semantics differ from in-place mutation. As a second option, audit and rewrite afterSanitizeElements and afterSanitizeAttributes hooks so they do not detach non-root elements - remove attributes or explicitly clear on* handlers and unwrap the node rather than deleting it - or, if deletion must remain, have the hook itself strip handlers from the detached subtree before returning; the trade-off is that this changes existing sanitization behavior and requires per-hook review, and any missed hook keeps the exposure. A restrictive Content-Security-Policy script-src directive or Trusted Types does not remove the defect but limits attacker script execution if a handler fires; it should be treated as defense in depth rather than a fix.
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 the widely deployed client-side HTML sanitizer maintained by Cure53 and shipped as the npm package dompurify (CPE cpe:2.3:a:cure53:dompurify:*:*:*:*:*:*:*:*). Its IN_PLACE mode is the unusual part: instead of returning a rebuilt, sanitized copy, it sanitizes the caller's live DOM subtree directly, mutating nodes the page has already inserted. That design creates a known hazard, previously addressed under GHSA-55q2-fjhq-7xh7, in which a hook detaches a node during sanitization; the library handles it with an internal guard (_handleHookDetachedNode, which calls _neutralizeSubtree when running in IN_PLACE) that strips non-allowlisted attributes - including on* handlers - from the detached subtree. Per the upstream advisory, that guard is wired only into the beforeSanitizeElements and uponSanitizeElement hook sites (src/purify.ts lines 2142 and 2175) and is missing from the afterSanitizeElements return paths (lines 2208 and 2249); _sanitizeAttributes fires afterSanitizeAttributes at line 2670 with no detach re-check and never calls the helper. The post-walk IN_PLACE neutralization pass (lines 3081-3090) iterates only DOMPurify.removed, and hook-detached nodes are deliberately excluded from that list (comment at lines 2096-2099), so nothing reaches them. The result is an instance of CWE-79 (improper neutralization of input during web page generation): markup whose on* handler sits inside a wrapper element removed by a node-deleting afterSanitize hook survives with its handler still bound to the live tree, and a resource-event handler that began loading while the caller built the tree (for example an img onerror) can fire in page scope even though the handler never appeared in the sanitized output. The vulnerable range is a narrow regression window, 3.4.13 through 3.4.15, fixed in 3.4.16.
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
Attacker only supplies markup (PR:N) but the required IN_PLACE-plus-node-removing-hook configuration is non-default (AC:H); victim must render content (UI:R), and XSS crosses into page scope (S:C) with limited C/I impact.
Primary rating from Vendor (VulnCheck).
CVSS VectorVendor: VulnCheck
Lifecycle Timeline
2DescriptionCVE.org
DOMPurify from 3.4.13 before 3.4.16 contains a cross-site scripting vulnerability because IN_PLACE mode fails to neutralize subtrees detached by afterSanitizeElements or afterSanitizeAttributes hooks. Attackers can supply markup with on* handlers inside a wrapper removed by such hooks, leaving handlers armed on the live DOM to execute script in the victim origin.
Blast Radius
ecosystem impact- 231 npm packages depend on dompurify (113 direct, 118 indirect)
Ecosystem-wide dependent count for version 3.4.13.
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-97646
GHSA-59fh-8xxf-p69h
NVD
CVE.org
EPSS
Exploit-DB