xmldom has XML injection through unvalidated DocumentType serialization
Date: 2026-04
Affected: npm/xmldom, npm/@xmldom/xmldom, npm/@xmldom/xmldom
Attack vector: other
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-41674
CVE-2026-41675
CWE: CWE-91

## Summary The package serializes `DocumentType` node fields (`internalSubset`, `publicId`, `systemId`) verbatim without any escaping or validation. When these fields are set programmatically to attacker-controlled strings, `XMLSerializer.serializeToString` can produce output where the DOCTYPE declaration is terminated early and arbitrary markup appears outside it. --- ## Details `DOMImplementation.createDocumentType(qualifiedName, publicId, systemId, internalSubset)` validates only `qualifiedName` against the XML QName production. The remaining three arguments are stored as-is with no validation. The XMLSerializer emits `DocumentType` nodes as: ``` <!DOCTYPE name[ PUBLIC pubid][ SYSTEM sysid][ [internalSubset]]> ``` All fields are pushed into the output buffer verbatim — no escaping, no quoting added. **`internalSubset` injection:** The serializer wraps `internalSubset` with ` [` and `]`. A value containing `]>` closes the internal subset and the DOCTYPE declaration at the injection point. Any content after `]>` in `internalSubset` appears outside the DOCTYPE in the serialized output as raw XML markup. Reported by @TharVid (GHSA-f6ww-3ggp-fr8h). Affected: `@xmldom/xmldom` ≥ 0.9.0 via `createDocumentType` API; 0.8.x only via direct property write. **`publicId` injection:** The serializer emits `publicId` verbatim after `PUBLIC` with no quoting added. A value containing an injected system identifier (e.g., `"pubid" SYSTEM "evil"`) breaks the intended quoting context,


Mitigations:

Architectural layers (MAESTRO):