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

CVE-2026-83614: xmldom JavaScript Library DOS Vulnerability

CVE-2026-83614 is a denial of service vulnerability in xmldom, a JavaScript W3C standard-based DOMParser library. Quadratic processing paths enable attackers to cause service disruption through malformed XML input.

Published:

CVE-2026-83614 Overview

CVE-2026-83614 is a denial-of-service vulnerability in the xmldom and @xmldom/xmldom JavaScript packages, which implement a W3C-standard DOMParser and XMLSerializer. The flaw consists of two independent quadratic-complexity paths [CWE-400]. In lib/sax.js, parseElementStartPart repeatedly rescans a malformed tag name during single-character recovery. In lib/dom.js, normalize() removes and appends adjacent text nodes one at a time, causing quadratic reindexing and string rebuilding. Both paths are reachable through the default DOMParser.parseFromString() API. Attackers can supply crafted XML input to exhaust CPU on any service that parses untrusted XML with the affected versions.

Critical Impact

Remote, unauthenticated attackers can trigger CPU exhaustion in any Node.js service that parses attacker-controlled XML using vulnerable versions of xmldom.

Affected Products

  • @xmldom/xmldom versions prior to 0.8.15
  • @xmldom/xmldom versions prior to 0.9.12
  • xmldom versions 0.3.0 through 0.6.0 (no fix available)

Discovery Timeline

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

Technical Details for CVE-2026-83614

Vulnerability Analysis

CVE-2026-83614 exposes two independent algorithmic-complexity flaws in xmldom. Both convert linear-size input into quadratic work, allowing small payloads to consume disproportionate CPU. The first path lives in the SAX tokenizer. When parseElementStartPart encounters an invalid character in a tag name, it advances one character and rescans forward to the next > or end-of-file. A document containing many < characters inside a malformed tag forces each one-character recovery step to rescan the entire remainder, producing O(n²) behavior.

The second path lives in the DOM normalize() implementation. The routine walks adjacent text nodes and, for each pair, calls removeChild followed by appendData. Each removeChild triggers an O(K) sibling reindex, and each appendData rebuilds a string, giving O(K²) cost across a run of K single-character text nodes. endDocument invokes normalize() automatically after parsing, so both paths are reachable through a single parseFromString() call.

Root Cause

The root cause is unbounded rescanning during error recovery in the tokenizer and per-node list-mutation cost during text-node coalescing. Neither routine tracks amortized work, so worst-case inputs cause repeated redundant traversal of the same data.

Attack Vector

An attacker submits crafted XML to any endpoint that parses it with vulnerable xmldom. No authentication or user interaction is required. Common exposure points include SAML processors, WebDAV handlers, RSS or Atom ingestion pipelines, and configuration importers.

javascript
// Security patch in lib/sax.js — prevent quadratic malformed-tag recovery
var s = S_TAG; //status
while (true) {
	var c = source.charAt(p);
	if (s === S_TAG && c === '<') {
		// A `<` can never occur inside a tag name. Without this guard the scan runs
		// on to the next `>` (or EOF) before `setTagName` rejects the whole slice, so
		// a document with many `<` inside a malformed tag makes each one-character
		// recovery step re-scan to the distant `>` — O(n^2). Stopping at the `<` keeps
		// each recovery step bounded.
		throw new Error('unexpected < in tag name: ' + source.slice(start, p));
	}
	switch (c) {
		case '=':
			if (s === S_ATTR) {
				// ...
			}
	}
}
// Source: https://github.com/xmldom/xmldom/commit/0748720b620555f8c222782dcab575cf0cf403b4

The companion fix in lib/dom.js batches adjacent text-node merges into a single O(K) pass instead of K individual removeChild/appendData operations. See the GitHub commit 0748720b for the full patch.

Detection Methods for CVE-2026-83614

Indicators of Compromise

  • Node.js processes pinned at 100% CPU while parsing XML, with stack traces referencing parseElementStartPart or normalize in xmldom.
  • Inbound XML payloads containing long sequences of < characters inside a malformed tag, or long runs of single-character text nodes.
  • Sudden latency spikes or request timeouts on endpoints that accept XML, SAML, or SOAP input.

Detection Strategies

  • Inventory application dependencies for xmldom and @xmldom/xmldom using npm ls xmldom @xmldom/xmldom or software composition analysis tooling.
  • Add request-size and parse-time limits to any XML-handling endpoint and alert when either threshold is crossed.
  • Correlate CPU-usage anomalies with request logs to identify sender addresses producing malformed XML.

Monitoring Recommendations

  • Track per-request XML parse duration and export it as a metric so quadratic behavior surfaces as a latency outlier.
  • Monitor for repeated Error: unexpected < in tag name exceptions after upgrading, indicating attack traffic that the patch now short-circuits.
  • Feed application and runtime telemetry into a centralized data lake to correlate CPU exhaustion with source IPs and payload signatures.

How to Mitigate CVE-2026-83614

Immediate Actions Required

  • Upgrade @xmldom/xmldom to version 0.8.15 or 0.9.12.
  • Remove any remaining use of the unmaintained xmldom package; no fixed version is available for versions 0.3.0 through 0.6.0.
  • Enforce request-size and parse-timeout limits on all endpoints that accept XML from untrusted sources.

Patch Information

The fix is delivered in @xmldom/xmldom 0.8.15 and @xmldom/xmldom 0.9.12. The changes are described in GHSA-93r5-fhx6-vmg9 and implemented in PR #1071 and PR #1072. The SAX patch aborts tag-name scanning when a < is encountered inside a tag. The DOM patch batches adjacent text-node merges into a single linear pass.

Workarounds

  • Cap the maximum size of XML documents accepted by the application, well below the payload sizes required to observe pathological behavior.
  • Wrap DOMParser.parseFromString() calls in a bounded worker or child process with a wall-clock timeout so a stuck parse cannot block the main event loop.
  • Where feasible, migrate to an actively maintained XML parser instead of the unmaintained xmldom package.
bash
# Upgrade to a fixed release
npm install @xmldom/xmldom@0.9.12

# Or, for the 0.8.x line
npm install @xmldom/xmldom@0.8.15

# Verify no vulnerable copies remain in the dependency tree
npm ls xmldom @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.