Misinterpretation of malicious XML input in xmldom
Description
xmldom is an open source pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module. xmldom versions 0.6.0 and older do not correctly escape special characters when serializing elements removed from their ancestor. This may lead to unexpected syntactic changes during XML processing in some downstream applications. This issue has been resolved in version 0.7.0. As a workaround downstream applications can validate the input and reject the maliciously crafted documents.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
xmldomnpm | <= 0.6.0 | — |
@xmldom/xmldomnpm | < 0.7.0 | 0.7.0 |
Affected products
1Patches
17b4b743917a8Merge pull request from GHSA-5fg8-2547-mr8q
2 files changed · +31 −11
lib/dom.js+12 −11 modified@@ -1129,6 +1129,15 @@ function needNamespaceDefine(node, isHTML, visibleNamespaces) { } return true; } +/** + * Well-formed constraint: No < in Attribute Values + * The replacement text of any entity referred to directly or indirectly in an attribute value must not contain a <. + * @see https://www.w3.org/TR/xml/#CleanAttrVals + * @see https://www.w3.org/TR/xml/#NT-AttValue + */ +function addSerializedAttribute(buf, qualifiedName, value) { + buf.push(' ', qualifiedName, '="', value.replace(/[<&"]/g,_xmlEncoder), '"') +} function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){ if (!visibleNamespaces) { @@ -1196,8 +1205,7 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){ if (needNamespaceDefine(attr,isHTML, visibleNamespaces)) { var prefix = attr.prefix||''; var uri = attr.namespaceURI; - var ns = prefix ? ' xmlns:' + prefix : " xmlns"; - buf.push(ns, '="' , uri , '"'); + addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri); visibleNamespaces.push({ prefix: prefix, namespace:uri }); } serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces); @@ -1207,8 +1215,7 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){ if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) { var prefix = node.prefix||''; var uri = node.namespaceURI; - var ns = prefix ? ' xmlns:' + prefix : " xmlns"; - buf.push(ns, '="' , uri , '"'); + addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri); visibleNamespaces.push({ prefix: prefix, namespace:uri }); } @@ -1247,13 +1254,7 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){ } return; case ATTRIBUTE_NODE: - /** - * Well-formedness constraint: No < in Attribute Values - * The replacement text of any entity referred to directly or indirectly in an attribute value must not contain a <. - * @see https://www.w3.org/TR/xml/#CleanAttrVals - * @see https://www.w3.org/TR/xml/#NT-AttValue - */ - return buf.push(' ', node.name, '="', node.value.replace(/[<&"]/g,_xmlEncoder), '"'); + return addSerializedAttribute(buf, node.name, node.value); case TEXT_NODE: /** * The ampersand character (&) and the left angle bracket (<) must not appear in their literal form,
test/dom/serializer.test.js+19 −0 modified@@ -120,4 +120,23 @@ describe('XML Serializer', () => { ) }) }) + describe('properly escapes attribute values', () => { + it('should escape special characters in namespace attributes', () => { + const input = `<xml xmlns='<&"' xmlns:attr='"&<'><test attr:test=""/></xml>` + const doc = new DOMParser().parseFromString(input, MIME_TYPE.XML_TEXT) + + // in this case the explicit attribute nodes are serialized + expect(new XMLSerializer().serializeToString(doc)).toBe( + '<xml xmlns="<&"" xmlns:attr=""&<"><test attr:test=""/></xml>' + ) + + // in this case the namespace attributes are "inherited" from the parent, + // which is not serialized + expect( + new XMLSerializer().serializeToString(doc.documentElement.firstChild) + ).toBe( + '<test xmlns:attr=""&<" attr:test="" xmlns="<&""/>' + ) + }) + }) })
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-5fg8-2547-mr8qghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-32796ghsaADVISORY
- github.com/xmldom/xmldom/commit/7b4b743917a892d407356e055b296dcd6d107e8bghsax_refsource_MISCWEB
- github.com/xmldom/xmldom/security/advisories/GHSA-5fg8-2547-mr8qghsax_refsource_CONFIRMWEB
- mattermost.com/blog/coordinated-disclosure-go-xml-vulnerabilitiesghsaWEB
- mattermost.com/blog/coordinated-disclosure-go-xml-vulnerabilities/mitrex_refsource_MISC
- mattermost.com/blog/securing-xml-implementations-across-the-webghsaWEB
- www.npmjs.com/package/@xmldom/xmldomghsaWEB
News mentions
0No linked articles in our index yet.