CVE-2026-83606: @xmldom/xmldom Processing Instruction ReDoS
Sending a single crafted XML document with an unterminated processing instruction and a long whitespace run to any Node.js server using @xmldom/xmldom 0.9.x can stall the event loop for seconds…

The problem
In @xmldom/xmldom 0.9.0-beta.9 through 0.9.10, the PI production in lib/grammar.js compiles a regex whose optional tail (?:S+(Char*?))? lets a greedy separator (S+) and a lazy data group (Char*?) both match XML whitespace.
When the required closing ?> is absent, the regex engine must ultimately fail, but first it tries every way to partition the whitespace run between the two groups. That is O(n^2) in the length of the trailing whitespace. Both parsePI and parseProcessingInstruction in lib/sax.js apply this regex to the entire remaining source string, so there is no natural bound on the input size.
Proof of concept
A working proof-of-concept for CVE-2026-83606 in @xmldom/xmldom, with the exact payload below.
const { DOMParser } = require('@xmldom/xmldom');
const n = 32 * 1024;
// unterminated PI: opens with <?p, then n spaces, never closes with ?>
const payload = '<a><?p' + ' '.repeat(n);
console.time('parse');
new DOMParser().parseFromString(payload, 'text/xml');
console.timeEnd('parse');
// Node 18: ~1 s at 32 KB, ~8 s at 64 KB (quadratic growth)The root cause (CWE-1333) is that S+ and Char*? overlap on whitespace. When the engine cannot match the mandatory ?>, it backtracks by shrinking S+ one character at a time and re-trying Char*? for each partition, producing O(n^2) work.
The patch (PR #1039, commit 73df6b8) inserts a fixed-width negative lookahead (?!\s) immediately after S+. This forces the data capture group to start only at a non-space character, making the partition unique and eliminating all backtracking. Measured improvement: 32 KB input drops from ~7777 ms to ~1 ms.
The fix
Upgrade @xmldom/xmldom to **0.9.11** or later. The 0.8.x LTS line and the unscoped xmldom package use an indexOf('?>')-bounded PI code path and are not affected by this specific issue. No configuration or workaround exists for affected 0.9.x versions short of upgrading.
Reported by jmestwa-coder.
Related research
- highCVE-2026-83619CVE-2026-83619: @xmldom/xmldom End-Tag Whitespace ReDoS
- highCVE-2026-83614CVE-2026-83614: @xmldom/xmldom Quadratic-Time Parsing ReDoS (DoS)
- highCVE-2026-83612CVE-2026-83612: @xmldom/xmldom HTML Raw-Text Closing-Tag Case Mismatch DoS
- highCVE-2026-83607CVE-2026-83607: @xmldom/xmldom Element Name Injection via createElement()