CVE-2026-41674
xmldom: XML injection through unvalidated DocumentType serialization
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
8.7
xmldom: XML injection through unvalidated DocumentType serialization
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
- Record
CVE-2026-41674- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-91, CWE-91
- Updated
- 2026-11-02
EUVDEUVD-2026-28289
8.7
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
- Record
EUVD-2026-28289- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-f6ww-3ggp-fr8h
8.7
xmldom has XML injection through unvalidated DocumentType serialization
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, injecting a fake SYSTEM entry
into the serialized DOCTYPE declaration. Identified during internal security research. Affected:
both branches, all versions back to 0.1.0.
systemId injection: The serializer emits systemId verbatim. A value containing >
terminates the DOCTYPE declaration early; content after > appears as raw XML markup outside
the DOCTYPE context. Identified during internal security research. Affected: both branches, all
versions back to 0.1.0.
The parse path is safe: the SAX parser enforces the PubidLiteral and SystemLiteral grammar
productions, which exclude the relevant characters, and the internal subset parser only accepts a
subset it can structurally validate. The vulnerability is reachable only through programmatic
createDocumentType calls with attacker-controlled arguments.
Affected code
lib/dom.js — createDocumentType (lines 898–910):
createDocumentType: function (qualifiedName, publicId, systemId, internalSubset) {
validateQualifiedName(qualifiedName); // only qualifiedName is validated
var node = new DocumentType(PDC);
node.name = qualifiedName;
node.nodeName = qualifiedName;
node.publicId = publicId || ''; // stored verbatim
node.systemId = systemId || ''; // stored verbatim
node.internalSubset = internalSubset || ''; // stored verbatim
node.childNodes = new NodeList();
return node;
},
lib/dom.js — serializer DOCTYPE case (lines 2948–2964):
case DOCUMENT_TYPE_NODE:
var pubid = node.publicId;
var sysid = node.systemId;
buf.push(g.DOCTYPE_DECL_START, ' ', node.name);
if (pubid) {
buf.push(' ', g.PUBLIC, ' ', pubid);
if (sysid && sysid !== '.') {
buf.push(' ', sysid);
}
} else if (sysid && sysid !== '.') {
buf.push(' ', g.SYSTEM, ' ', sysid);
}
if (node.internalSubset) {
buf.push(' [', node.internalSubset, ']'); // internalSubset emitted verbatim
}
buf.push('>');
return;
PoC
internalSubset injection
const { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');
const impl = new DOMImplementation();
const doctype = impl.createDocumentType(
'root',
'',
'',
']><injected/><![CDATA['
);
const doc = impl.createDocument(null, 'root', doctype);
const xml = new XMLSerializer().serializeToString(doc);
console.log(xml);
// <!DOCTYPE root…
- Record
GHSA-f6ww-3ggp-fr8h- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-91
- Updated
- 2026-11-02
NVD
8.7
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
- Record
CVE-2026-41674- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Weakness
- CWE-91
- Updated
- 2026-11-02
OSV
8.7
xmldom: XML injection through unvalidated DocumentType serialization
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
- Record
CVE-2026-41674- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-91
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-41674
8.7
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
- Record
DEBIAN-CVE-2026-41674- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
Show 7 moreShow less
OSVGHSA-f6ww-3ggp-fr8h
8.7
xmldom has XML injection through unvalidated DocumentType serialization
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, injecting a fake SYSTEM entry
into the serialized DOCTYPE declaration. Identified during internal security research. Affected:
both branches, all versions back to 0.1.0.
systemId injection: The serializer emits systemId verbatim. A value containing >
terminates the DOCTYPE declaration early; content after > appears as raw XML markup outside
the DOCTYPE context. Identified during internal security research. Affected: both branches, all
versions back to 0.1.0.
The parse path is safe: the SAX parser enforces the PubidLiteral and SystemLiteral grammar
productions, which exclude the relevant characters, and the internal subset parser only accepts a
subset it can structurally validate. The vulnerability is reachable only through programmatic
createDocumentType calls with attacker-controlled arguments.
Affected code
lib/dom.js — createDocumentType (lines 898–910):
createDocumentType: function (qualifiedName, publicId, systemId, internalSubset) {
validateQualifiedName(qualifiedName); // only qualifiedName is validated
var node = new DocumentType(PDC);
node.name = qualifiedName;
node.nodeName = qualifiedName;
node.publicId = publicId || ''; // stored verbatim
node.systemId = systemId || ''; // stored verbatim
node.internalSubset = internalSubset || ''; // stored verbatim
node.childNodes = new NodeList();
return node;
},
lib/dom.js — serializer DOCTYPE case (lines 2948–2964):
case DOCUMENT_TYPE_NODE:
var pubid = node.publicId;
var sysid = node.systemId;
buf.push(g.DOCTYPE_DECL_START, ' ', node.name);
if (pubid) {
buf.push(' ', g.PUBLIC, ' ', pubid);
if (sysid && sysid !== '.') {
buf.push(' ', sysid);
}
} else if (sysid && sysid !== '.') {
buf.push(' ', g.SYSTEM, ' ', sysid);
}
if (node.internalSubset) {
buf.push(' [', node.internalSubset, ']'); // internalSubset emitted verbatim
}
buf.push('>');
return;
PoC
internalSubset injection
const { DOMImplementation, XMLSerializer } = require('@xmldom/xmldom');
const impl = new DOMImplementation();
const doctype = impl.createDocumentType(
'root',
'',
'',
']><injected/><![CDATA['
);
const doc = impl.createDocument(null, 'root', doctype);
const xml = new XMLSerializer().serializeToString(doc);
console.log(xml);
// <!DOCTYPE root…
- Record
GHSA-f6ww-3ggp-fr8h- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-91
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-41674
8.7
xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. In @xmldom/xmldom prior to versions 0.9.10 and 0.8.13 and xmldom version 0.6.0 and prior, 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. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.
- Record
UBUNTU-CVE-2026-41674- CVSS 4.0
- 8.7 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N - Updated
- 2026-11-02
OSVCLSA-2026-1778114663 No score
TuxCare security update for xmldom (1 CVE)
TuxCare rebuilt xmldom to address 1 CVE. Fixed in 0.6.0-tuxcare.3.
- Record
CLSA-2026-1778114663- Updated
- 2026-11-02
OSVCLSA-2026-1786447648 No score
TuxCare security update for xmldom (1 CVE)
TuxCare rebuilt xmldom to address 1 CVE. Fixed in 0.1.31-tuxcare.3.
- Record
CLSA-2026-1786447648- Updated
- 2026-11-02
OSVCLSA-2026-1790755546 No score
TuxCare security update for @xmldom/xmldom (14 CVEs)
TuxCare rebuilt @xmldom/xmldom to address 14 CVEs. Fixed in 0.7.13-tuxcare.1.
- Record
CLSA-2026-1790755546- Updated
- 2026-11-02
OSVCLSA-2026-1791192659 No score
TuxCare security update for @xmldom/xmldom (10 CVEs)
TuxCare rebuilt @xmldom/xmldom to address 10 CVEs. Fixed in 0.9.8-tuxcare.2.
- Record
CLSA-2026-1791192659- Updated
- 2026-11-02
OSVROOT-APP-NPM-CVE-2026-41674 No score
CVE-2026-41674 in @xmldom/xmldom - Patched by Root
Root has patched CVE-2026-41674 in the @xmldom/xmldom package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-41674- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@xmldom/xmldomnpm |
before 0.8.13 | 0.8.13 |
@xmldom/xmldomnpm |
0.9.0 up to 0.9.10 | 0.9.10 |
xmldomnpm |
through 0.6.0 | None known |
xmldomTuxCare:npm |
0.6.0-tuxcare.0 up to 0.6.0-tuxcare.3, plus listed versions 0.6.00.6.0-tuxcare.10.6.0-tuxcare.2 |
0.6.0-tuxcare.3 |
xmldomTuxCare:npm |
0.1.31-tuxcare.0 up to 0.1.31-tuxcare.3, plus listed versions 0.1.310.1.31-tuxcare.10.1.31-tuxcare.2 |
0.1.31-tuxcare.3 |
@xmldom/xmldomTuxCare:npm From an advisory covering 14 CVEs |
0.7.13-tuxcare.0 up to 0.7.13-tuxcare.1, plus listed versions 0.7.13 |
0.7.13-tuxcare.1 |
@xmldom/xmldomTuxCare:npm From an advisory covering 8 CVEs |
0.9.8-tuxcare.0 up to 0.9.8-tuxcare.2, plus listed versions 0.9.80.9.8-tuxcare.1 |
0.9.8-tuxcare.2 |
node-xmldomDebian:12 |
All versions, plus listed versions 0.8.6-10.9.10-10.9.10-20.9.11-10.9.12-1 Show 5 moreShow less0.9.5-10.9.6-10.9.8-10.9.8-20.9.9-1 |
None known |
node-xmldomDebian:13 |
All versions, plus listed versions 0.9.10-10.9.10-20.9.11-10.9.12-10.9.6-10.9.8-10.9.8-20.9.9-1 |
None known |
node-xmldomDebian:14 |
before 0.9.10-1, plus listed versions 0.9.6-10.9.8-10.9.8-20.9.9-1 |
0.9.10-1 |
Show 8 moreShow less
| Package | Affected | Fixed |
|---|---|---|
@xmldom/xmldomRoot:npm |
before 0.7.13-aikido.2 | 0.7.13-aikido.20.7.13-aikido.30.9.8-aikido.20.8.11-aikido.20.7.13-aikido.50.8.13-aikido.20.7.13-aikido.40.8.13-aikido.1 |
@rootio/xmldom__xmldomRoot:npm |
before 0.9.8-root.io.1 | 0.9.8-root.io.10.8.11-root.io.10.7.13-root.io.10.7.13-root.io.20.7.13-root.io.30.9.8-root.io.20.8.11-root.io.20.7.13-root.io.50.8.13-root.io.20.7.13-root.io.40.8.13-root.io.1 |
node-xmldomUbuntu:20.04:LTS |
All versions, plus listed versions 0.1.27+ds-10.1.27+ds-1+deb10u2build0.20.04.1 |
None known |
node-xmldomUbuntu:22.04:LTS |
All versions, plus listed versions 0.5.0-10.7.3-10.7.5-10.7.5-1ubuntu0.22.04.1 |
None known |
node-xmldomUbuntu:24.04:LTS |
All versions, plus listed versions 0.8.6-1 |
None known |
node-xmldomUbuntu:25.10 |
All versions, plus listed versions 0.9.6-1 |
None known |
node-xmldomUbuntu:26.10 |
All versions, plus listed versions 0.9.8-20.9.10-20.9.11-1 |
None known |
node-xmldomUbuntu:26.04:LTS |
All versions, plus listed versions 0.9.6-10.9.8-10.9.8-2 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-41674 is a high vulnerability (CVSS 8.7) in Xmldom, published April 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.56%, the 47th percentile. Fixed in @xmldom/xmldom 0.8.13.
References
github.com/xmldom/xmldom/security/advisories/GHSA-f6ww-3ggp-fr8h
github.com/xmldom/xmldom/commit/372008f9ae0e20fd69f761c7b79e202598267314
github.com/xmldom/xmldom/releases/tag/0.8.13
github.com/xmldom/xmldom/releases/tag/0.9.10
access.redhat.com/security/cve/CVE-2026-41674
bugzilla.redhat.com/show_bug.cgi?id=2467620
Show 12 moreShow less
security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-41674.json
access.redhat.com/errata/RHSA-2026:21338
access.redhat.com/errata/RHSA-2026:26234
access.redhat.com/errata/RHSA-2026:21703
access.redhat.com/errata/RHSA-2026:20034
nvd.nist.gov/vuln/detail/CVE-2026-41674
github.com/advisories/GHSA-f6ww-3ggp-fr8h
github.com/CVEProject/cvelistV5/tree/main/cves/2026/41xxx/CVE-2026-41674.json
security-tracker.debian.org/tracker/CVE-2026-41674
github.com/xmldom/xmldom
ubuntu.com/security/CVE-2026-41674
cve.org/CVERecord?id=CVE-2026-41674
Left out here: the rest of 2 source descriptions. The JSON record has them.