VYPR
High severityNVD Advisory· Published May 7, 2026· Updated May 7, 2026

CVE-2026-41672

CVE-2026-41672

Description

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 allows attacker-controlled comment content to be serialized into XML without validating or neutralizing comment-breaking sequences. As a result, an attacker can terminate the comment early and inject arbitrary XML nodes into the serialized output. This issue has been patched in versions @xmldom/xmldom versions 0.9.10 and 0.8.13.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@xmldom/xmldomnpm
< 0.8.130.8.13
@xmldom/xmldomnpm
>= 0.9.0, < 0.9.100.9.10
xmldomnpm
<= 0.6.0

Affected products

1

Patches

2
b39754088908

fix: prevent XML injection via unsafe comment serialization (GHSA-j759-j44w-7fr8)

https://github.com/xmldom/xmldomkarfauApr 11, 2026via ghsa
3 files changed · +59 3
  • index.d.ts+8 3 modified
    @@ -25,8 +25,11 @@ declare module "@xmldom/xmldom" {
       /** Options accepted by `XMLSerializer.prototype.serializeToString`. */
       interface XMLSerializerOptions {
           /**
    -       * When `true`, the serializer throws a DOMException with code `INVALID_STATE_ERR` if the
    -       * CDATASection data contains `"]]>"`.
    +       * When `true`, the serializer throws a DOMException with code `INVALID_STATE_ERR` if:
    +       * - A CDATASection node's data contains `"]]>"`.
    +       * - A Comment node's data contains `"-->"` (the injection sequence that terminates a
    +       *   comment). Comments whose data contains `"--"` but not `"-->"` are accepted on this
    +       *   branch — the 0.8.x parser does not validate bare `"--"` in comment content.
            *
            * @default false
            */
    @@ -50,7 +53,9 @@ declare module "@xmldom/xmldom" {
            *
            * @throws {DOMException}
            * With code `INVALID_STATE_ERR` when `requireWellFormed` is `true` and the CDATASection
    -       * data contains `"]]>"`.
    +       * data contains `"]]>"`, or a Comment node's data contains `"-->"`.
    +       * (On this 0.8.x branch, bare `"--"` in comment data does not throw — see
    +       * `XMLSerializerOptions.requireWellFormed` for details.)
            * @see https://html.spec.whatwg.org/#dom-xmlserializer-serializetostring
            * @see https://github.com/w3c/DOM-Parsing/issues/84
            */
    
  • lib/dom.js+11 0 modified
    @@ -1506,6 +1506,11 @@ function XMLSerializer(){}
      * @throws {DOMException}
      * With code `INVALID_STATE_ERR` when `requireWellFormed` is `true` and the CDATASection
      * data contains `"]]>"`.
    + * With code `INVALID_STATE_ERR` when `requireWellFormed` is `true` and a Comment node's
    + * data contains `"-->"` (the injection sequence that terminates a comment and allows
    + * arbitrary XML to follow). Comments whose data contains `"--"` but not `"-->"` are
    + * accepted — the 0.8.x parser does not validate bare `"--"` inside comment content,
    + * so throwing would break a previously-working round-trip.
      * @see https://html.spec.whatwg.org/#dom-xmlserializer-serializetostring
      * @see https://github.com/w3c/DOM-Parsing/issues/84
      */
    @@ -1733,6 +1738,12 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces,requireW
     		}
     		return buf.push('<![CDATA[', node.data.replace(/]]>/g, ']]]]><![CDATA[>'), ']]>');
     	case COMMENT_NODE:
    +		if (requireWellFormed && node.data.indexOf('-->') !== -1) {
    +			throw new DOMException(
    +				INVALID_STATE_ERR,
    +				'The comment node data contains "-->"'
    +			);
    +		}
     		return buf.push( "<!--",node.data,"-->");
     	case DOCUMENT_TYPE_NODE:
     		var pubid = node.publicId;
    
  • test/dom/serializer.test.js+40 0 modified
    @@ -387,4 +387,44 @@ describe('XMLSerializer serializeToString requireWellFormed option', () => {
     			doc.toString(false, null, { requireWellFormed: true })
     		).toThrow(DOMException)
     	})
    +
    +	describe('Comment', () => {
    +		it('default: comment with "-->" in data emits verbatim — no throw', () => {
    +			const comment = doc.createComment('safe-->evil')
    +			doc.documentElement.appendChild(comment)
    +			expect(new XMLSerializer().serializeToString(doc.documentElement)).toBe(
    +				'<root><!--safe-->evil--></root>'
    +			)
    +		})
    +
    +		it('requireWellFormed: true on comment with "-->" throws InvalidStateError', () => {
    +			const comment = doc.createComment('safe-->evil')
    +			doc.documentElement.appendChild(comment)
    +			expect(() =>
    +				new XMLSerializer().serializeToString(doc, false, null, {
    +					requireWellFormed: true,
    +				})
    +			).toThrow(DOMException)
    +		})
    +
    +		it('requireWellFormed: true on comment with "--" (no "-->") does not throw — intentional on 0.8.x', () => {
    +			const comment = doc.createComment('hello--world')
    +			doc.documentElement.appendChild(comment)
    +			expect(
    +				new XMLSerializer().serializeToString(doc, false, null, {
    +					requireWellFormed: true,
    +				})
    +			).toBe('<root><!--hello--world--></root>')
    +		})
    +
    +		it('requireWellFormed: true on comment with clean data serializes correctly', () => {
    +			const comment = doc.createComment('safe comment')
    +			doc.documentElement.appendChild(comment)
    +			expect(
    +				new XMLSerializer().serializeToString(doc, false, null, {
    +					requireWellFormed: true,
    +				})
    +			).toBe('<root><!--safe comment--></root>')
    +		})
    +	})
     })
    
fda7cc313de3

fix: prevent XML injection via unsafe comment serialization (GHSA-j759-j44w-7fr8)

https://github.com/xmldom/xmldomkarfauApr 11, 2026via ghsa
3 files changed · +76 5
  • index.d.ts+8 2 modified
    @@ -1209,6 +1209,11 @@ declare module '@xmldom/xmldom' {
     		/**
     		 * Creates a comment object with the specified data.
     		 *
    +		 * No validation is performed at creation time. When the resulting document is serialized
    +		 * with `requireWellFormed: true`, the serializer throws `InvalidStateError` if the comment
    +		 * data contains `--` anywhere, ends with `-`, or contains characters outside the XML Char
    +		 * production (W3C DOM Parsing §3.2.1.3). Without that option the data is emitted verbatim.
    +		 *
     		 * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createComment)
     		 */
     		createComment(data: string): Comment;
    @@ -1470,8 +1475,9 @@ declare module '@xmldom/xmldom' {
     	interface XMLSerializerOptions {
     		/**
     		 * When `true`, the serializer throws `InvalidStateError` for content that would produce
    -		 * ill-formed XML (CDATASection data containing `"]]>"`, Text data with characters outside
    -		 * the XML Char production, or a Document with no `documentElement`).
    +		 * ill-formed XML: CDATASection data containing `"]]>"`; Text data with characters outside
    +		 * the XML Char production; a Comment node whose data contains `--` anywhere or ends with
    +		 * `-`; or a Document with no `documentElement`.
     		 *
     		 * @default false
     		 */
    
  • lib/dom.js+24 3 modified
    @@ -2218,6 +2218,15 @@ Document.prototype = {
     	/**
     	 * @param {string} data
     	 * @returns {Comment}
    +	 * @see https://dom.spec.whatwg.org/#dom-document-createcomment
    +	 * @see https://www.w3.org/TR/xml/#NT-Comment XML 1.0 production [15]
    +	 * @see https://www.w3.org/TR/DOM-Parsing/#dfn-concept-serialize-xml §3.2.1.3
    +	 *
    +	 *      Note: no validation is performed at creation time. When the resulting document is
    +	 *      serialized with `requireWellFormed: true`, the serializer throws `InvalidStateError`
    +	 *      if the comment data contains `--` anywhere, ends with `-`, or contains characters
    +	 *      outside the XML Char production (W3C DOM Parsing §3.2.1.3). Without that option the
    +	 *      data is emitted verbatim.
     	 */
     	createComment: function (data) {
     		var node = new Comment(PDC);
    @@ -2761,9 +2770,10 @@ function XMLSerializer() {}
      * A filter function applied to each node before serialization.
      * @returns {string}
      * @throws {DOMException}
    - * With name `InvalidStateError` when `requireWellFormed` is `true` and the CDATASection data
    - * contains `"]]>"`, Text data contains characters outside the XML Char production, or the
    - * Document has no `documentElement`.
    + * With name `InvalidStateError` when `requireWellFormed` is `true` and any of the following
    + * conditions hold: CDATASection data contains `"]]>"`; Text data contains characters outside
    + * the XML Char production; a Comment node's data contains `--` anywhere or ends with `-`;
    + * the Document has no `documentElement`.
      * @see https://html.spec.whatwg.org/#dom-xmlserializer-serializetostring
      * @see https://github.com/w3c/DOM-Parsing/issues/84
      */
    @@ -3022,6 +3032,17 @@ function serializeToString(node, buf, visibleNamespaces, opts) {
     			}
     			return buf.push(g.CDATA_START, node.data, g.CDATA_END);
     		case COMMENT_NODE:
    +			if (requireWellFormed) {
    +				if (g.InvalidChar.test(node.data)) {
    +					throw new DOMException(
    +						'The comment node data contains characters outside the XML Char production',
    +						'InvalidStateError'
    +					);
    +				}
    +				if (node.data.indexOf('--') !== -1 || node.data[node.data.length - 1] === '-') {
    +					throw new DOMException('The comment node data contains "--" or ends with "-"', 'InvalidStateError');
    +				}
    +			}
     			return buf.push(g.COMMENT_START, node.data, g.COMMENT_END);
     		case DOCUMENT_TYPE_NODE:
     			var pubid = node.publicId;
    
  • test/dom/serializer.test.js+44 0 modified
    @@ -309,6 +309,50 @@ describe('XMLSerializer.serializeToString', () => {
     				expect(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true })).not.toThrow();
     			});
     		});
    +
    +		describe('Comment', () => {
    +			test('default: comment with "-->" in data emits verbatim — no throw', () => {
    +				doc.documentElement.appendChild(doc.createComment('hello-->world'));
    +				expect(new XMLSerializer().serializeToString(doc)).toBe('<root><!--hello-->world--></root>');
    +			});
    +
    +			test('default: comment with "--" in data emits verbatim — no throw', () => {
    +				doc.documentElement.appendChild(doc.createComment('hello--world'));
    +				expect(new XMLSerializer().serializeToString(doc)).toBe('<root><!--hello--world--></root>');
    +			});
    +
    +			test('requireWellFormed: true on comment with invalid XML Char (\\x00) throws InvalidStateError', () => {
    +				doc.documentElement.appendChild(doc.createComment('hello\x00world'));
    +				expectDOMException(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true }), 'InvalidStateError');
    +			});
    +
    +			test('requireWellFormed: true on comment with "-->" throws InvalidStateError', () => {
    +				doc.documentElement.appendChild(doc.createComment('hello-->world'));
    +				expectDOMException(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true }), 'InvalidStateError');
    +			});
    +
    +			test('requireWellFormed: true on comment with "--" (no "-->") throws InvalidStateError', () => {
    +				doc.documentElement.appendChild(doc.createComment('hello--world'));
    +				expectDOMException(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true }), 'InvalidStateError');
    +			});
    +
    +			test('requireWellFormed: true on comment whose data ends with "-" throws InvalidStateError', () => {
    +				doc.documentElement.appendChild(doc.createComment('hello-'));
    +				expectDOMException(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true }), 'InvalidStateError');
    +			});
    +
    +			test('requireWellFormed: true on comment with clean data does not throw', () => {
    +				doc.documentElement.appendChild(doc.createComment('clean comment'));
    +				expect(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true })).not.toThrow();
    +			});
    +
    +			test('mutation vector: appendData("-->") then requireWellFormed: true throws InvalidStateError', () => {
    +				const comment = doc.createComment('clean');
    +				doc.documentElement.appendChild(comment);
    +				comment.appendData('-->');
    +				expectDOMException(() => new XMLSerializer().serializeToString(doc, { requireWellFormed: true }), 'InvalidStateError');
    +			});
    +		});
     	});
     });
     
    

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

News mentions

1