CVE-2026-83612: @xmldom/xmldom HTML Raw-Text Closing-Tag Case Mismatch DoS
A tiny crafted HTML document with mixed-case closing tags on script, style, textarea, or title elements causes @xmldom/xmldom to produce output that grows quadratically, exhausting CPU and memory in…

The problem
In HTML mode, parseHtmlSpecialContent searches for a raw-text element's closing tag using a byte-for-byte case-sensitive indexOf. When the closing tag differs in case from the opener (e.g. </ScRiPt> for <script>), the search returns -1.
The subsequent source.substring(elStartEnd + 1, -1) then extracts text backwards from the document start. The function returns -1 to the parse loop, which cannot advance and falls back to character-by-character reprocessing. Each additional mismatched element re-captures all preceding source text, so output grows O(n²).
An 18 KB input can serialize to roughly 9 MB, enough to exhaust heap or stall an event loop.
Proof of concept
A working proof-of-concept for CVE-2026-83612 in @xmldom/xmldom, with the exact payload below.
const { DOMParser, XMLSerializer } = require('@xmldom/xmldom');
const n = 1000;
const payload = '<html><body>' + '<script>x</ScRiPt>'.repeat(n) + '</body></html>';
const doc = new DOMParser().parseFromString(payload, 'text/html');
const out = new XMLSerializer().serializeToString(doc);
console.log(payload.length, out.length, (out.length / payload.length).toFixed(1) + 'x');
// 18026 9037063 501.3x — 18 KB input yields ~9 MB outputThree bugs compose the vulnerability. First, source.indexOf('</' + tagName + '>', elStartEnd) in lib/sax.js:549 is case-sensitive, so a mixed-case closer never matches and returns -1. Second, source.substring(elStartEnd + 1, elEndStart) at line 550 runs unguarded when elEndStart === -1, extracting all text from position 0 backwards.
Third, returning -1 at line 556 prevents the parse loop from advancing, forcing a character-by-character fallback that re-captures all preceding source text on every iteration.
The fix replaces the case-sensitive indexOf with a case-insensitive search (per the WHATWG HTML RAWTEXT end-tag-name state rule) and adds an explicit guard for a missing closing tag, making progression stable and output size linear.
The fix
Upgrade @xmldom/xmldom to **0.9.12** or later. Only the 0.9.x line is affected; 0.8.x is not vulnerable to this amplification. No configuration change is needed alongside the upgrade.
Reported by KarimTantawey.
Related research
- highCVE-2026-83614CVE-2026-83614: @xmldom/xmldom Quadratic-Time Parsing ReDoS (DoS)
- highCVE-2026-83619CVE-2026-83619: @xmldom/xmldom End-Tag Whitespace ReDoS
- highCVE-2026-83606CVE-2026-83606: @xmldom/xmldom Processing Instruction ReDoS
- highCVE-2026-83607CVE-2026-83607: @xmldom/xmldom Element Name Injection via createElement()