Hoch

xmldom PI grammar regex ReDoS: quadratic backtracking on unterminated processing instructions

  • Veröffentlicht: 08.09.2026
  • Aktualisiert: 11.10.2026 10:22

Summary

@xmldom/xmldom's processing-instruction (PI) grammar regex exhibits quadratic-time backtracking (ReDoS) when parsing an unterminated processing instruction. A single small XML document containing <? + a target + a long run of whitespace and no closing ?> forces the regular expression engine into O(n²) work, stalling the Node.js event loop. The input is parsed with DOMParser.parseFromString under default options, so it is reachable from unauthenticated, network-delivered XML (SOAP/SAML, webhooks, uploads, XML APIs).

Details

The PI production in lib/grammar.js compiles (flags mu) to:

^<\?(NameChars)(?:[\x20\x09\x0D\x0A]+([Char]*?))?\?>
                     ^^^ S+ greedy       ^^^ Char*? lazy

In the optional tail (?:S+(Char*?))?, both the greedy separator S+ and the lazy data Char*? match XML whitespace. When the required trailing ?> is absent, the engine must ultimately fail — but first it tries every partition of the whitespace run between S+ and Char*?, which is O(n²) in the length of the trailing whitespace.

The regex is executed against the entire remaining source string in two places in lib/sax.js, so the whole whitespace tail is scanned:

Affected Versions

Only the 0.9.x line is affected. lib/grammar.js (and this PI regex) was introduced in commit 726b471 ("fix!: preserve DOCTYPE internal subset (#498)"), first released in 0.9.0-beta.9, and is unchanged through 0.9.10.

The 0.8.x line (≤ 0.8.13) and the unscoped xmldom package (≤ 0.6.0) parse PIs via a different code path bounded by indexOf('?>') — they do not contain this regex and are not affected by this issue. (They were not separately tested for a different PI ReDoS; the scope here is the specific grammar.js regex.)

Line PI code path Affected?
0.9.x (0.9.0-beta.9 … 0.9.10) grammar.js PI regex over full remaining source Yes
0.8.x (≤ 0.8.13) parseInstruction, bounded by indexOf('?>') No
unscoped xmldom (≤ 0.6.0) older indexOf('?>')-bounded parsing No

Proof of Concept

js
const { DOMParser } = require('@xmldom/xmldom');
const n = 32 * 1024;
const payload = '<a><?p' + ' '.repeat(n); // unterminated PI, no `?>`
console.time('parse');
new DOMParser().parseFromString(payload, 'text/xml');
console.timeEnd('parse');

Measured (Node 18), trailing whitespace after <?p, no ?> — time quadruples per doubling of input length (canonical O(n²)):

Trailing whitespace g.PI.exec parseFromString
2 KB 4.4 ms 5.1 ms
4 KB 16.9 ms 17.0 ms
8 KB 111.4 ms 66.3 ms
16 KB 263.8 ms 336.5 ms
32 KB 1073.1 ms —

Impact

Availability only: a single parse of a small crafted document blocks the Node.js event loop for the duration of the quadratic scan (≈1 s at 32 KB; multi-second with larger inputs). No memory blow-up, no data exposure, no integrity impact. Because XML is routinely accepted from untrusted sources and parsed with default options, one request can stall a server.

Fix Applied

Fixed in @xmldom/xmldom 0.9.11 (0.9.x-only; the 0.8.x LTS line and the unscoped xmldom package use a different, bounded PI code path and are not affected).

PR #1039 inserts a fixed-width negative lookahead (?!\s) immediately after the greedy S+, so the separator can no longer hand whitespace back to the lazy data group:

- var PI = reg(/^<\?/, '(', Name, ')', regg(S, '(', Char, '*?)'), '?', /\?>/);
+ var PI = reg(/^<\?/, '(', Name, ')', regg(S, '(?!', _SChar, ')(', Char, '*?)'), '?', /\?>/);

The change is correct, minimal, and behavior-preserving: it produces identical [target, data] captures on all valid PIs tested (incl. whitespace-heavy, tab/newline, empty-data, and xml-decl cases) and removes the backtracking blow-up (linear, ~0.4 ms at 128 KB after the fix). The lookahead is fixed-width and cannot itself backtrack — a strict improvement with no new parsing risk.

Severity note

The complexity is quadratic, not exponential, so a multi-second stall requires tens-to-hundreds of KB of input. VA:H reflects that xmldom applies no input-size limit and the path runs on default-options parsing, so a single unbounded parse can fully stall the event loop.

Betroffene Software

Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.

PlattformPaketAnfällige VersionenBehoben in
npm-Paket @xmldom/xmldom >= 0.9.0-beta.9, < 0.9.11 0.9.11

Verweise

CVSS-Wert -
CVSS-Vektor
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Schwäche (CWE)
CWE-1333, CWE-400
Plattform
npm
Paket
@xmldom/xmldom
Veröffentlicht
08.09.2026
Aktualisiert
11.10.2026 10:22

Quellen und Lizenzen

OSV / GitHub Advisory Database - GHSA-g53g-w8rj-fmg7 - CC BY 4.0

Schwachstellenhistorie: @xmldom/xmldom

Alle veröffentlichten Schwachstellen dieses Pakets (npm-Paket), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.

Alle (22) im Archiv
Einträge insgesamt
22
Erste → letzte
08.2021 09.2026
Ohne Fix
0
In Angriffen ausgenutzt
0

Verteilung nach Schweregrad

  • Kritisch 1
  • Hoch 18
  • Mittel 3

Veröffentlichungen pro Jahr

  1. 2021: 1
  2. 2022: 1
  3. 2023: 0
  4. 2024: 0
  5. 2025: 0
  6. 2026: 20
Schweregrad:
  1. Hoch CVE-2026-83616 >= 0.7.0, < 0.8.15, >= 0.9.0, < 0.9.12 0.8.15, 0.9.12
  2. Hoch CVE-2026-83608 >= 0.7.0, < 0.8.15, >= 0.9.0, < 0.9.12 0.8.15, 0.9.12
  3. Hoch CVE-2026-83613 >= 0.7.0, < 0.8.15, >= 0.9.0, < 0.9.12 0.8.15, 0.9.12
  4. Hoch CVE-2026-83615 >= 0.7.0, < 0.8.15, >= 0.9.0, < 0.9.12 0.8.15, 0.9.12
  5. Hoch CVE-2026-83612 >= 0.9.0-beta.1, < 0.9.12 0.9.12
  6. xmldom PI grammar regex ReDoS: quadratic backtracking on unterminated processing instructions dieser Eintrag
    Hoch CVE-2026-83606 >= 0.9.0-beta.9, < 0.9.11 0.9.11
  7. Hoch CVE-2026-83607 >= 0.9.0, < 0.9.11, >= 0.7.0, < 0.8.14 0.9.11, 0.8.14
  8. Hoch CVE-2026-83605 >= 0.9.0, < 0.9.11, >= 0.7.0, < 0.8.14 0.9.11, 0.8.14
  9. Hoch CVE-2026-41673 < 0.8.13, >= 0.9.0, < 0.9.10 0.8.13, 0.9.10
  10. Hoch CVE-2026-41674 < 0.8.13, >= 0.9.0, < 0.9.10 0.8.13, 0.9.10
  11. Hoch CVE-2026-41675 < 0.8.13, >= 0.9.0, < 0.9.10 0.8.13, 0.9.10
  12. Hoch CVE-2026-41672 < 0.8.13, >= 0.9.0, < 0.9.10 0.8.13, 0.9.10
  13. Hoch · 7.5 CVE-2026-34601 < 0.8.12, >= 0.9.0, < 0.9.9 0.8.12, 0.9.9
  14. Kritisch · 9.8 CVE-2022-39353 < 0.7.7, >= 0.8.0, < 0.8.4, >= 0.9.0-beta.1, < 0.9.0-beta.4 0.7.7, 0.8.4, 0.9.0-beta.4

Erkennen Sie Schwachstellen in Ihrer Anwendung

Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.

Anwendung verbinden
DockRay Newsletter

Anwendungssicherheit in Ihrem Postfach

Wichtige Schwachstellen, konkrete Empfehlungen und praktische Tipps für Ihre Anwendungen. Wählen Sie Ihre Technologien und verfolgen Sie, was für Ihr Projekt relevant ist.

  • Eine tägliche Zusammenfassung neuer Schwachstellen, auch kritischer.
  • Benachrichtigungen über wichtige Updates.
  • Praktische Tipps zur Sicherheit und Überwachung von Anwendungen.

Leer lassen, um Meldungen zu allen Technologien zu erhalten.

Kostenlos anmelden. In jeder E-Mail mit einem Klick abmelden.