CSIRTS // UNIFIED SECURITY ADVISORY FEEDSYS ● ONLINE · POWERED BY INTELFUSIONS.COM

GHSA-x4vx-rjvf-j5p4: DOMPurify: `IN_PLACE` mode trusts attacker-controlled `nodeName` on live non-form nodes, allowing script retention and XSS via attacker-supplied DOM objects

lowCVE-2026-65901
Summary When DOMPurify.sanitize(root, { IN_PLACE: true }) is called on an attacker-supplied live DOM node, DOMPurify still trusts currentNode.nodeName for non-form nodes in the main _sanitizeElements pipeline. A real <script> child node whose observable nodeName is attacker-controlled can therefore be misclassified as an allowed element and retained. When the sanitized tree is inserted into a live document, the script executes. This affects current 3.4.6. The recent IN_PLACE hardening work covers clobbered form handling and foreign-realm shadow/template traversal, but does not harden the main per-node element decision for hostile non-form live nodes. Affected - DOMPurify 3.4.6 - Any caller that does DOMPurify.sanitize(node, { IN_PLACE: true }) on attacker-supplied live DOM nodes - Verified attacker-controlled node sources: - same-origin iframe → live node passed by reference - same-origin window.open() popup → live node passed by reference - same-origin foreign node adopted into the host document via document.adoptNode(node) and then sanitized in-place Not affected: - String-input DOMPurify.sanitize(dirtyString) Vulnerability details Code paths [A] — _sanitizeElements uses the instance-visible nodeName for the allow/forbid decision: const _sanitizeElements = function (currentNode: any): boolean { ... if (_isClobbered(currentNode)) { _forceRemove(currentNode); return true; } const tagName = transformCaseFunc(currentNode.nodeName); ... if ( FORBID_TAGS[tagName] || (!(...) && !ALLOWED_TAGS[tagName]) ) { ... _forceRemove(currentNode); return true; } ... }; For non-form nodes, _isClobbered(currentNode) returns false early. The subsequent element decision therefore trusts currentNode.nodeName directly. [B] — _isClobbered is form-specific: const _isClobbered = function (element: Element): boolean { const realTagName = getNodeName ? getNodeName(element) : null; if (typeof realTagName !== 'string') { return false; } if (transformCaseFunc(realTagName) !== 'form

Details

Source
GitHub Security Advisories (INTL · database · site)
Severity
low
Published
2026-06-15
Last updated
2026-07-23
Exploitation
Not in CISA KEV at last sync

Original advisory: https://github.com/advisories/GHSA-x4vx-rjvf-j5p4

Exploitation outlook

EPSS (FIRST.org) estimates each CVE’s probability of exploitation in the next 30 days — here is the CSIRTS.com read on those numbers.

Referenced CVEs

CVECSIRTS overviewExternal
CVE-2026-65901coverage & exploitation statusNVD · CVE.org

Same CVEs, other sources

How other CERTs, PSIRTs and databases cover the vulnerabilities in this advisory.

More from GitHub Security Advisories