Every CVE Search/ Get API key

CVE-2026-109344

DOMPurify from 3.4.13 before 3.4.16 DOM XSS via IN_PLACE afterSanitize Hooks

5.1 MediumFix available

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.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
Active

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
None

Exploit likelihood

0.19%Unchanged since Oct 13, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.1

DOMPurify from 3.4.13 before 3.4.16 DOM XSS via IN_PLACE afterSanitize Hooks

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.

Record
CVE-2026-109344
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
EUVDEUVD-2026-97646 5.1

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.

Record
EUVD-2026-97646
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-59fh-8xxf-p69h 5.1

DOMPurify from 3.4.13 before 3.4.16 contains a cross-site scripting vulnerability because...

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.

Record
GHSA-59fh-8xxf-p69h
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/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
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
GitHub AdvisoriesGHSA-p98j-92pf-mc4p 2.3

DOMPurify: IN_PLACE: node-removing afterSanitize hook leaves detached subtree event handlers armed, causing DOM XSS

Summary

In IN_PLACE mode DOMPurify sanitizes the caller's live DOM subtree directly. To close a known hazard (GHSA-55q2-fjhq-7xh7), the library neutralizes any node a hook detaches during sanitization by stripping its subtree's non-allow-listed attributes, but this neutralization is wired only into the beforeSanitizeElements and uponSanitizeElement hook sites. An afterSanitizeElements or afterSanitizeAttributes hook that removes a non-root element (a documented, supported pattern) detaches that element's subtree with no neutralization, so descendant on* handlers remain armed on the caller's live tree after sanitize() returns, yielding DOM XSS. No special privilege is required beyond supplying markup to an application that uses IN_PLACE together with a node-removing afterSanitize hook.

Root Cause

IN_PLACE sanitization mutates the caller's live document, so any element a hook detaches from that tree must have its subtree neutralized before sanitize() returns; otherwise a queued resource-event handler (for example an <img onerror> that began loading when the caller built the tree) fires in page scope even though the handler never reached the sanitized output. The guard helper _handleHookDetachedNode (which calls _neutralizeSubtree in IN_PLACE) is invoked only after beforeSanitizeElements and after uponSanitizeElement. It is never invoked from the afterSanitize return paths, and _sanitizeAttributes never calls it at all. The post-walk IN_PLACE neutralization pass iterates only DOMPurify.removed, and hook-detached nodes are intentionally not recorded there, so that pass cannot reach them either.

src/purify.ts
  _sanitizeElements: _handleHookDetachedNode present at lines 2142 and 2175
    (before/upon), absent after afterSanitizeElements at lines 2208 and 2249.
  _sanitizeAttributes: afterSanitizeAttributes fires at line 2670 with no
    detach re-check; the function never calls _handleHookDetachedNode.
  Post-walk IN_PLACE pass (lines 3081-3090) iterates DOMPurify.removed only,
    which by design (comment at lines 2096-2099) excludes hook-detached nodes.

Impact

An attacker who supplies markup processed by a victim application that runs DOMPurify.sanitize(node, { IN_PLACE: true }) and registers a node-removing afterSanitizeElements or afterSanitizeAttributes hook can retain arbitrary on* event handlers on descendants of a removed non-root element. Because IN_PLACE operates on the caller's live document, a queued resource-event handler on such a descendant fires in the page origin after the synchronous sanitize() call returns, giving script execution in the victim's session (DOM XSS). This defeats DOMPurify's IN_PLACE contract to neutralize handlers on subtrees removed from the live tree. The capability is script execution in the victim origin; exact confidentiality and integrity effects depend on the hosting application's session.

Proof of Concept

Dependencies: Node.js and jsdom. The harness builds a live tree, registers a
removal hook, runs IN_PLACE sanitize(), then inspects whether the attacker
onerror handler survives on the detached descendant. jsdom does not perform
real image loads, so the retained handler (rather than an actual fired event)
is the observed hazard; the retained on* attribute on a live detached node
after a synchronous sanitize() return is the neutralization failure.

Reproduction steps:

  1. Build a live subtree #root > section#wrap > img[onerror] where #root is the walk root and section#wrap is a non-root wrapper.
  2. Register an afterSanitizeElements (or afterSanitizeAttributes) hook that calls node.remove() on the wrapper.
  3. Call DOMPurify.sanitize(root, { IN_PLACE: true }).
  4. Observe that the descendant <img> retains its onerror handler, whereas the same removal performed in a beforeSanitizeElements/uponSanitizeElement hook strips it.
const { JSDOM } = require('jsdom');…
Record
GHSA-p98j-92pf-mc4p
CVSS 4.0
2.3 LowCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-79
Updated
2026-11-02
NVD 5.1

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.

Record
CVE-2026-109344
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/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
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Weakness
CWE-79
Updated
2026-11-02
OSV 5.1

DOMPurify from 3.4.13 before 3.4.16 DOM XSS via IN_PLACE afterSanitize Hooks

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.

Record
CVE-2026-109344
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N
Weakness
CWE-79
Updated
2026-11-02
Show 6 moreShow less
OSVDEBIAN-CVE-2026-109344 5.1

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.

Record
DEBIAN-CVE-2026-109344
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/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
Updated
2026-11-02
OSVGHSA-p98j-92pf-mc4p 2.3

DOMPurify: IN_PLACE: node-removing afterSanitize hook leaves detached subtree event handlers armed, causing DOM XSS

Summary

In IN_PLACE mode DOMPurify sanitizes the caller's live DOM subtree directly. To close a known hazard (GHSA-55q2-fjhq-7xh7), the library neutralizes any node a hook detaches during sanitization by stripping its subtree's non-allow-listed attributes, but this neutralization is wired only into the beforeSanitizeElements and uponSanitizeElement hook sites. An afterSanitizeElements or afterSanitizeAttributes hook that removes a non-root element (a documented, supported pattern) detaches that element's subtree with no neutralization, so descendant on* handlers remain armed on the caller's live tree after sanitize() returns, yielding DOM XSS. No special privilege is required beyond supplying markup to an application that uses IN_PLACE together with a node-removing afterSanitize hook.

Root Cause

IN_PLACE sanitization mutates the caller's live document, so any element a hook detaches from that tree must have its subtree neutralized before sanitize() returns; otherwise a queued resource-event handler (for example an <img onerror> that began loading when the caller built the tree) fires in page scope even though the handler never reached the sanitized output. The guard helper _handleHookDetachedNode (which calls _neutralizeSubtree in IN_PLACE) is invoked only after beforeSanitizeElements and after uponSanitizeElement. It is never invoked from the afterSanitize return paths, and _sanitizeAttributes never calls it at all. The post-walk IN_PLACE neutralization pass iterates only DOMPurify.removed, and hook-detached nodes are intentionally not recorded there, so that pass cannot reach them either.

src/purify.ts
  _sanitizeElements: _handleHookDetachedNode present at lines 2142 and 2175
    (before/upon), absent after afterSanitizeElements at lines 2208 and 2249.
  _sanitizeAttributes: afterSanitizeAttributes fires at line 2670 with no
    detach re-check; the function never calls _handleHookDetachedNode.
  Post-walk IN_PLACE pass (lines 3081-3090) iterates DOMPurify.removed only,
    which by design (comment at lines 2096-2099) excludes hook-detached nodes.

Impact

An attacker who supplies markup processed by a victim application that runs DOMPurify.sanitize(node, { IN_PLACE: true }) and registers a node-removing afterSanitizeElements or afterSanitizeAttributes hook can retain arbitrary on* event handlers on descendants of a removed non-root element. Because IN_PLACE operates on the caller's live document, a queued resource-event handler on such a descendant fires in the page origin after the synchronous sanitize() call returns, giving script execution in the victim's session (DOM XSS). This defeats DOMPurify's IN_PLACE contract to neutralize handlers on subtrees removed from the live tree. The capability is script execution in the victim origin; exact confidentiality and integrity effects depend on the hosting application's session.

Proof of Concept

Dependencies: Node.js and jsdom. The harness builds a live tree, registers a
removal hook, runs IN_PLACE sanitize(), then inspects whether the attacker
onerror handler survives on the detached descendant. jsdom does not perform
real image loads, so the retained handler (rather than an actual fired event)
is the observed hazard; the retained on* attribute on a live detached node
after a synchronous sanitize() return is the neutralization failure.

Reproduction steps:

  1. Build a live subtree #root > section#wrap > img[onerror] where #root is the walk root and section#wrap is a non-root wrapper.
  2. Register an afterSanitizeElements (or afterSanitizeAttributes) hook that calls node.remove() on the wrapper.
  3. Call DOMPurify.sanitize(root, { IN_PLACE: true }).
  4. Observe that the descendant <img> retains its onerror handler, whereas the same removal performed in a beforeSanitizeElements/uponSanitizeElement hook strips it.
const { JSDOM } = require('jsdom');…
Record
GHSA-p98j-92pf-mc4p
CVSS 4.0
2.3 LowCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-79
Updated
2026-11-02
OSVUBUNTU-CVE-2026-109344 5.1

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.

Record
UBUNTU-CVE-2026-109344
CVSS 4.0
5.1 MediumCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N
CVSS 3.1
6.1 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
Updated
2026-11-02
OSVCLSA-2026-1790884902 No score

TuxCare security update for dompurify (1 CVE)

TuxCare rebuilt dompurify to address 1 CVE. Fixed in 3.4.14-tuxcare.1.

Record
CLSA-2026-1790884902
Updated
2026-11-02
OSVCLSA-2026-1792508927 No score

TuxCare security update for dompurify (2 CVEs)

TuxCare rebuilt dompurify to address 2 CVEs. Fixed in 3.4.13-tuxcare.1.

Record
CLSA-2026-1792508927
Updated
2026-11-02
OSVCLSA-2026-1792509241 No score

TuxCare security update for dompurify (2 CVEs)

TuxCare rebuilt dompurify to address 2 CVEs. Fixed in 3.4.15-tuxcare.1.

Record
CLSA-2026-1792509241
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
dompurify
npm
3.4.13 to 3.4.15
3.4.16
dompurify
TuxCare:npm
3.4.14-tuxcare.0 up to 3.4.14-tuxcare.1, plus listed versions
3.4.14
3.4.14-tuxcare.1
dompurify
TuxCare:npm
From an advisory covering 2 CVEs
3.4.13-tuxcare.0 up to 3.4.13-tuxcare.1, plus listed versions
3.4.13
3.4.13-tuxcare.1
dompurify
TuxCare:npm
From an advisory covering 2 CVEs
3.4.15-tuxcare.0 up to 3.4.15-tuxcare.1, plus listed versions
3.4.15
3.4.15-tuxcare.1
node-dompurify
Debian:12
All versions, plus listed versions
2.4.1+dfsg+~2.4.0-12.4.1+dfsg+~2.4.0-22.4.1+dfsg+~2.4.0-2+deb12u13.0.9+dfsg+~3.0.5-13.1.6+dfsg+~3.0.5-1
Show 13 moreShow less
3.1.7+dfsg+~3.0.5-13.1.7+dfsg+~3.0.5-23.2.5+dfsg-13.3.2+dfsg-13.3.3+dfsg-13.3.3+dfsg-23.4.1+dfsg-13.4.12+dfsg-13.4.13+dfsg-13.4.13+dfsg-23.4.16+dfsg-13.4.2+dfsg-13.4.5+dfsg-1
None known
node-dompurify
Debian:13
All versions, plus listed versions
3.1.7+dfsg+~3.0.5-23.2.5+dfsg-13.3.2+dfsg-13.3.3+dfsg-13.3.3+dfsg-2
Show 7 moreShow less
3.4.1+dfsg-13.4.12+dfsg-13.4.13+dfsg-13.4.13+dfsg-23.4.16+dfsg-13.4.2+dfsg-13.4.5+dfsg-1
None known
node-dompurify
Debian:14
before 3.4.16+dfsg-1, plus listed versions
3.1.7+dfsg+~3.0.5-23.2.5+dfsg-13.3.2+dfsg-13.3.3+dfsg-13.3.3+dfsg-2
Show 6 moreShow less
3.4.1+dfsg-13.4.12+dfsg-13.4.13+dfsg-13.4.13+dfsg-23.4.2+dfsg-13.4.5+dfsg-1
3.4.16+dfsg-1
dompurify
npm
3.4.13 up to 3.4.16
3.4.16
node-dompurify
Ubuntu:22.04:LTS
All versions, plus listed versions
2.3.0+dfsg-22.3.3+dfsg-1
None known
node-dompurify
Ubuntu:24.04:LTS
All versions, plus listed versions
2.4.1+dfsg+~2.4.0-13.0.9+dfsg+~3.0.5-1
None known
node-dompurify
Ubuntu:26.10
All versions, plus listed versions
3.3.3+dfsg-13.4.2+dfsg-13.4.5+dfsg-13.4.12+dfsg-13.4.13+dfsg-13.4.13+dfsg-2
None known
node-dompurify
Ubuntu:26.04:LTS
All versions, plus listed versions
3.1.7+dfsg+~3.0.5-23.3.3+dfsg-1
None known

History

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

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

In short

CVE-2026-109344 is a medium vulnerability (CVSS 5.1) in Cure53 Dompurify, published September 30, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.19%, the 8th percentile. Fixed in dompurify 3.4.16.

References

Show 7 moreShow less
This page doesn't list everything

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

MoveEnter Open