Skip to main content
Vulnerability Database/CVE-2026-83605

CVE-2026-83605: xmldom XSS Vulnerability in setAttribute

CVE-2026-83605 is a cross-site scripting vulnerability in xmldom that enables attackers to inject malicious attributes through unchecked attribute names in Element.setAttribute(). This article covers technical details, affected versions, and mitigation strategies.

Published:

CVE-2026-83605 Overview

CVE-2026-83605 affects @xmldom/xmldom, a pure JavaScript W3C standard-based DOMParser and XMLSerializer module widely used in Node.js applications. The vulnerability allows attackers to inject arbitrary attributes, including event handlers, into serialized XML output. The flaw resides in Element.setAttribute(), which calls the private _createAttribute(name) path without validating the attribute name against the XML QName production. XMLSerializer.serializeToString() then emits these unchecked names verbatim, and the requireWellFormed: true option fails to enforce validation.

Critical Impact

A crafted attribute name can terminate the intended attribute and inject additional attributes, including JavaScript event handlers, into browser-consumed output — leading to cross-site scripting (XSS) in downstream consumers.

Affected Products

  • @xmldom/xmldom versions prior to 0.8.14
  • @xmldom/xmldom versions prior to 0.9.11
  • xmldom version 0.6.0 and earlier (no fixed version available)

Discovery Timeline

  • 2026-09-01 - CVE-2026-83605 published to NVD
  • 2026-09-01 - Last updated in NVD database

Technical Details for CVE-2026-83605

Vulnerability Analysis

The vulnerability is classified as [CWE-91] XML Injection (aka Blind XPath Injection), stemming from improper neutralization of special elements in XML attribute names. When an application calls Element.setAttribute(name, value) with untrusted input for name, the library routes the call through _createAttribute(name) without validating the identifier against the XML QName grammar. In contrast, Document.createAttribute(name) does perform QName validation, creating an inconsistent security boundary within the same API surface.

During serialization, XMLSerializer.serializeToString() writes the attribute name directly to the output stream. Even when callers opt into strict output with requireWellFormed: true, the pre-fix implementation did not check attribute qualified names. Synthesized xmlns:PREFIX namespace declarations expose the same unchecked-name boundary, allowing prefix-based injection paths.

Root Cause

The root cause is missing input validation on the attribute-creation code path used by Element.setAttribute(). The W3C DOM Parsing specification §3.2.1.1 requires well-formedness checks on element localNames, prefixes, and attribute serialization when requireWellFormed is true. These checks were not implemented, so any string — including one containing " or > — was accepted and emitted verbatim.

Attack Vector

An attacker supplies a crafted attribute name such as x="" onload="alert(1)" to code that forwards user input into setAttribute(). When the resulting DOM is serialized and consumed by a browser, the injected event handler executes in the victim's origin. The attack requires no authentication and no user interaction beyond viewing the rendered output.

javascript
// Patch excerpt: lib/dom.js — QName validation now imported and enforced
var find = conventions.find;
var NAMESPACE = conventions.NAMESPACE;
var tagNamePattern = conventions.tagNamePattern;

/**
 * A prerequisite for `[].filter`, to drop elements that are empty
 */

Source: GitHub commit d8212e6

typescript
// Patch excerpt: index.d.ts — new DOMException conditions when requireWellFormed is true
// - an Element's qualified name (including any namespace prefix) is not a valid XML QName,
// - an attribute's qualified name (including a synthesized `xmlns:` namespace declaration)
//   is not a valid XML QName,
// - a CDATASection node's data contains `"]]>"`,
// - a Comment node's data contains `"-->"`
// - a ProcessingInstruction's data contains `"?>"`

Source: GitHub commit cba1321

Detection Methods for CVE-2026-83605

Indicators of Compromise

  • Serialized XML or HTML output containing unexpected attributes such as onload, onerror, onclick, or onmouseover originating from server-side rendering pipelines that use xmldom.
  • Presence of vulnerable @xmldom/xmldom versions (< 0.8.14 or >= 0.9.0, < 0.9.11) or any xmldom version in package.json or package-lock.json.
  • Unexpected xmlns: prefix declarations in serialized output that were not present in application source data.

Detection Strategies

  • Run npm audit or yarn audit to identify vulnerable xmldom and @xmldom/xmldom versions in dependency trees, including transitive dependencies.
  • Add static analysis rules (Semgrep, ESLint) that flag calls to setAttribute() where the attribute name argument is not a string literal or a validated identifier.
  • Perform dynamic testing by fuzzing endpoints that produce XML or HTML with attribute names containing quotes, spaces, and angle brackets.

Monitoring Recommendations

  • Log and alert on Content Security Policy (CSP) violations in browser telemetry, which may signal successful injection into consumed XML output.
  • Monitor Software Composition Analysis (SCA) tooling for advisory GHSA-4w3w-2rp5-g8jm on new builds.
  • Review web application firewall (WAF) logs for request payloads containing double quotes or event-handler keywords targeting fields that later populate XML attribute names.

How to Mitigate CVE-2026-83605

Immediate Actions Required

  • Upgrade @xmldom/xmldom to version 0.8.14 or 0.9.11 immediately in all projects and rebuild dependent applications.
  • Migrate away from the deprecated xmldom package, which has no fixed release, to the maintained @xmldom/xmldom fork.
  • Audit application code for callers that pass untrusted input as the name argument to Element.setAttribute() or Document.createAttribute().

Patch Information

The fix is available in GitHub Release v0.8.14 and GitHub Release v0.9.11. The patches introduce QName validation on the setAttribute() code path and enforce attribute-name checks when requireWellFormed: true is set. See Pull Request #1043, Pull Request #1050, and the GitHub Security Advisory GHSA-4w3w-2rp5-g8jm for full details.

Workarounds

  • Validate attribute names against the XML QName regular expression before passing them to setAttribute(); reject any input containing whitespace, quotes, or >.
  • Prefer Document.createAttribute(name) followed by setAttributeNode(), since createAttribute already validates names against QName.
  • Apply strict output encoding and a restrictive Content Security Policy on downstream consumers to reduce the impact of any residual attribute injection.
bash
# Upgrade to a patched version
npm install @xmldom/xmldom@0.9.11
# or for the 0.8.x line
npm install @xmldom/xmldom@0.8.14

# Verify the installed version
npm ls @xmldom/xmldom

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.