CVE-2026-83606 Overview
CVE-2026-83606 is a denial-of-service vulnerability in @xmldom/xmldom, a pure JavaScript W3C standard-based DOMParser and XMLSerializer module widely used in Node.js applications. The flaw resides in the processing-instruction grammar production inside lib/grammar.js. When an XML input contains an unterminated processing instruction with a long whitespace tail, the regular expression backtracks quadratically, stalling the Node.js event loop. The issue affects versions 0.9.0-beta.9 through 0.9.10 and is fixed in 0.9.11. An unauthenticated remote attacker can trigger the condition with a small crafted XML payload.
Critical Impact
A small unauthenticated XML input can stall the Node.js event loop, blocking all concurrent request processing on affected servers.
Affected Products
- @xmldom/xmldom versions 0.9.0-beta.9 through 0.9.10
- Node.js applications invoking DOMParser.parseFromString() under default options
- Downstream libraries and frameworks bundling vulnerable @xmldom/xmldom releases
Discovery Timeline
- 2026-09-01 - CVE-2026-83606 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-83606
Vulnerability Analysis
The defect is a Regular Expression Denial of Service (ReDoS) issue classified under [CWE-400: Uncontrolled Resource Consumption]. The processing-instruction (PI) production combines a greedy S+ whitespace matcher with a lazy Char*? data group. When the required closing ?> sequence is absent, the regex engine repeatedly repartitions the trailing whitespace between the two groups, producing quadratic runtime relative to input length. Both parsePI and parseProcessingInstruction apply the expression against the entire remaining source buffer. Because parsing occurs on the main thread, the stall blocks the Node.js event loop and prevents servicing any other request.
Root Cause
The root cause is grammar ambiguity in the PI regular expression. The overlap between S+ and Char*? creates multiple valid match partitions when the terminator is missing. The engine explores each partition through backtracking before failing.
Attack Vector
An unauthenticated attacker submits a small XML document to any endpoint that calls DOMParser.parseFromString(). The payload begins a processing instruction with a Name token, includes a long whitespace tail, and omits the closing ?> delimiter. Parsing consumes CPU proportional to the square of the tail length, halting other event-loop work.
// Security patch in lib/grammar.js (source: xmldom commit 73df6b8)
// - var PI = reg(/^<\?/, '(', Name, ')', regg(S, '(', Char, '*?)'), '?', /\?>/);
// + var PI = reg(/^<\?/, '(', Name, ')',
// + regg(S, '(?!', _SChar, ')(', Char, '*?)'), '?', /\?>/);
//
// The added negative lookahead `(?!S)` after the greedy `S+` asserts the
// data starts with a non-whitespace character. This prunes the overlapping
// partitions that caused quadratic backtracking on unterminated PIs.
Source: xmldom commit 73df6b8bdbd86f904b9e8c3ab9c49aa54ef2802e
Detection Methods for CVE-2026-83606
Indicators of Compromise
- Sudden increase in Node.js event-loop lag or request-handler timeout errors on services that parse XML.
- HTTP request bodies containing <? followed by a Name token, extended whitespace, and no ?> terminator.
- Elevated single-core CPU utilization on Node.js workers correlated with inbound XML traffic.
Detection Strategies
- Inventory Node.js dependencies with npm ls @xmldom/xmldom and flag any version below 0.9.11 in the 0.9.x line.
- Deploy Software Composition Analysis (SCA) rules that alert on the GHSA-g53g-w8rj-fmg7 advisory.
- Add web application firewall (WAF) signatures that inspect XML bodies for unterminated processing instructions.
Monitoring Recommendations
- Instrument applications with event-loop lag metrics and alert when the p99 latency exceeds a baseline threshold.
- Log XML parser exceptions and processing durations for every DOMParser.parseFromString() invocation.
- Rate-limit unauthenticated endpoints that accept XML payloads and enforce a maximum request body size.
How to Mitigate CVE-2026-83606
Immediate Actions Required
- Upgrade @xmldom/xmldom to version 0.9.11 or later across all Node.js services and container images.
- Rebuild and redeploy any downstream libraries that vendor or bundle the vulnerable release.
- Apply request size limits and timeouts to endpoints that invoke XML parsing while patches roll out.
Patch Information
The fix is available in @xmldom/xmldom release 0.9.11, delivered via pull request #1039. The patch adds a negative lookahead in the PI grammar so the data segment must start with a non-whitespace character, eliminating the ambiguous partition that caused quadratic backtracking. Details are documented in GitHub Security Advisory GHSA-g53g-w8rj-fmg7.
Workarounds
- Reject XML inputs larger than a defined byte threshold before passing them to the parser.
- Wrap DOMParser.parseFromString() calls in a worker thread with an execution timeout to isolate stalls.
- Pre-validate XML with a lightweight sanity check that rejects unterminated <? sequences.
# Upgrade to the fixed release
npm install @xmldom/xmldom@0.9.11
# Verify no vulnerable versions remain in the dependency tree
npm ls @xmldom/xmldom
# Audit for advisories affecting installed packages
npm audit --production
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.