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

CVE-2026-83612: xmldom HTML Parser DOS Vulnerability

CVE-2026-83612 is a denial of service vulnerability in xmldom that causes CPU and memory exhaustion through HTML parsing flaws. Small untrusted documents can trigger quadratic output amplification. This article covers technical details, affected versions, impact assessment, and mitigation strategies.

Published:

CVE-2026-83612 Overview

CVE-2026-83612 affects @xmldom/xmldom, a pure JavaScript W3C standard-based DOMParser and XMLSerializer module widely used across Node.js and browser applications. Versions from 0.9.0-beta.1 through 0.9.11 mishandle mixed-case closing tags for HTML raw-text elements including script, style, textarea, and title. When DOMParser.parseFromString() processes these elements in HTML mode, a case-sensitive search fails to locate the closing tag, triggering unstable parser progression and quadratic output amplification. A small untrusted text/html document can consume disproportionate CPU and memory during parsing and serialization, enabling a denial-of-service condition against any service that parses attacker-controlled HTML.

Critical Impact

A minimal untrusted HTML input can trigger quadratic CPU and memory amplification, exhausting resources on servers that parse attacker-supplied documents.

Affected Products

  • @xmldom/xmldom version 0.9.0-beta.1 through 0.9.11
  • Node.js and JavaScript applications embedding vulnerable xmldom releases
  • Downstream libraries and frameworks depending on @xmldom/xmldom in HTML-mode parsing

Discovery Timeline

  • 2026-09-01 - CVE-2026-83612 published to NVD
  • 2026-09-01 - Last updated in NVD database
  • Fix released - @xmldom/xmldom version 0.9.12 published with the patch

Technical Details for CVE-2026-83612

Vulnerability Analysis

The defect resides in parseHtmlSpecialContent inside lib/sax.js. When the parser encounters an HTML raw-text or escapable raw-text element, it locates the matching end tag using source.indexOf('</' + tagName + '>', elStartEnd). This lookup is case-sensitive, but the WHATWG HTML specification (§13.2.5.14 RAWTEXT end tag name state) requires case-insensitive matching for closing tags. When a mixed-case closer such as </Script> follows a lowercase <script> opener, indexOf() returns -1.

The returned -1 is then passed directly to source.substring(elStartEnd + 1, -1). JavaScript treats a negative end index as 0, so the call silently produces a backward slice interpreted as an empty or reversed range. The parser fails to advance correctly and re-emits accumulated source content on subsequent iterations. Repeated raw-text elements amplify the output quadratically relative to input size. This behavior maps to [CWE-178: Improper Handling of Case Sensitivity].

Root Cause

The root cause is a case-sensitivity mismatch between the parser implementation and the HTML specification, compounded by unchecked use of the indexOf() sentinel value. The code does not validate that a closing tag was actually found before slicing, so a -1 return propagates into substring() and drives runaway output growth during serialization.

Attack Vector

Exploitation requires only that an application pass attacker-controlled HTML into DOMParser.parseFromString() in HTML mode. No authentication, user interaction, or privileged access is required. A remote attacker submits a compact HTML payload containing raw-text elements terminated with mixed-case closers such as </SCRIPT>, </Style>, or </TeXtArEa>. Parsing and serialization then consume CPU and memory at a rate quadratic in the number of affected elements, producing a resource-exhaustion denial of service.

javascript
// Security patch in lib/sax.js from @xmldom/xmldom 0.9.12
// TODO: https://html.spec.whatwg.org/#cdata-rcdata-restrictions
var isEscapableRaw = isHTMLEscapableRawTextElement(tagName);
if (isEscapableRaw || isHTMLRawTextElement(tagName)) {
	// The closing tag of a raw-text element matches case-insensitively
	// (WHATWG HTML §13.2.5.14 RAWTEXT end tag name state). A case-sensitive
	// search that missed the closing tag would return -1 and the `substring`
	// below would treat -1 as a backward slice from position 0, re-emitting all
	// prior source and amplifying output quadratically across repeated elements.
	// The regex is anchored to `elStartEnd` via `lastIndex` so it scans forward
	// only (O(distance), not the whole source).
	var closeTag = new RegExp('</' + tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '>', 'ig');
	closeTag.lastIndex = elStartEnd;
	var match = closeTag.exec(source);
	var elEndStart = match ? match.index : -1;
	if (elEndStart < 0) {
		// No closing tag: never slice with a -1 end index. Leave the element to
		// the parse loop's normal recovery instead of back-capturing the source.
		return elStartEnd + 1;
	}
	var text = source.substring(elStartEnd + 1, elEndStart);

	if (isEscapableRaw) {

Source: GitHub Commit 7ced40c

Detection Methods for CVE-2026-83612

Indicators of Compromise

  • Sustained CPU saturation in Node.js processes correlated with inbound HTTP requests carrying text/html payloads.
  • Rapid heap growth or out-of-memory terminations in services invoking DOMParser.parseFromString().
  • Request bodies containing raw-text elements (<script>, <style>, <textarea>, <title>) closed with mixed-case tags such as </Script> or </TITLE>.

Detection Strategies

  • Perform software composition analysis to enumerate applications resolving @xmldom/xmldom at versions 0.9.0-beta.1 through 0.9.11.
  • Instrument HTML parsing paths with per-request CPU and wall-clock budgets to surface anomalous parse durations.
  • Alert on repeated occurrences of mixed-case raw-text closing tags in inbound HTML bodies at the WAF or reverse proxy.

Monitoring Recommendations

  • Track event loop lag and worker thread stalls on services that accept user-submitted HTML.
  • Correlate application memory pressure with request identifiers to isolate malicious payloads.
  • Log and rate-limit endpoints that invoke DOM parsing on untrusted input.

How to Mitigate CVE-2026-83612

Immediate Actions Required

  • Upgrade @xmldom/xmldom to version 0.9.12 or later across all applications and transitive dependencies.
  • Audit dependency lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml) to confirm no vulnerable versions remain resolved.
  • Rebuild and redeploy container images and serverless bundles that embed the vulnerable package.

Patch Information

The issue is fixed in @xmldom/xmldom version 0.9.12. The patch replaces the case-sensitive indexOf() lookup with a case-insensitive regular expression anchored to the current parse position and returns early when no closing tag is found, preventing the negative-index substring() slice. See the GitHub Security Advisory GHSA-6mj3-qw4j-hgrw, Pull Request #1071, and Release v0.9.12 notes.

Workarounds

  • Restrict or sanitize untrusted HTML before it reaches DOMParser.parseFromString(), stripping raw-text elements when feasible.
  • Enforce request body size limits and parse timeouts on any endpoint that accepts HTML input.
  • Isolate HTML parsing in a worker with strict CPU and memory quotas to contain resource exhaustion.
bash
# Upgrade the vulnerable package to the patched release
npm install @xmldom/xmldom@0.9.12

# Verify no vulnerable versions remain in the dependency tree
npm ls @xmldom/xmldom

# For yarn or pnpm environments
yarn up @xmldom/xmldom@0.9.12
pnpm update @xmldom/xmldom@0.9.12

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.