GitHub Advisoryadvisory · npm

GHSA-m7jm-9gc2-mpf2 fast-xml-parser has an entity encoding bypass via regex injection in DOCTYPE entity names

CRITICAL Published 2026-02-20 Modified 2026-02-27 Official page ↗
Aliases
CVE-2026-25896
Ecosystem
npm
Packages
fast-xml-parser
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:H/A:N
Weaknesses
CWE-185
Reviewed
2026-02-20

Affected packages

• npm fast-xml-parser: >= 5.0.0, < 5.3.5 → fixed in 5.3.5 • npm fast-xml-parser: >= 4.1.3, < 4.5.4 → fixed in 4.5.4

Description

Entity encoding bypass via regex injection in DOCTYPE entity names Summary A dot (`.`) in a DOCTYPE entity name is treated as a regex wildcard during entity replacement, allowing an attacker to shadow built-in XML entities (`&lt;`, `&gt;`, `&amp;`, `&quot;`, `&apos;`) with arbitrary values. This bypasses entity encoding and leads to XSS when parsed output is rendered. Details The fix for CVE-2023-34104 addressed some regex metacharacters in entity names but missed `.` (period), which is valid in XML names per the W3C spec. In `DocTypeReader.js`, entity names are passed directly to `RegExp()`: ```js entities[entityName] = { regx: RegExp(`&${entityName};`, "g"), val: val }; ``` An entity named `l.` produces the regex `/&l.;/g` where `.` matches any character, including the `t` in `&lt;`. Since DOCTYPE entities are replaced before built-in entities, this shadows `&lt;` entirely. The same issue exists in `OrderedObjParser.js:81` (`addExternalEntities`), and in the v6 codebase - `EntitiesParser.js` has a `validateEntityName` function with a character blacklist, but `.` is not included: ```js // v6 EntitiesParser.js line 96 const specialChar = "!?\\/[]$%{}^&*()<>|+"; // no dot ``` Shadowing all 5 built-in entities | Entity name | Regex created | Shadows | |---|---|---| | `l.` | `/&l.;/g` | `&lt;` | | `g.` | `/&g.;/g` | `&gt;` | | `am.` | `/&am.;/g` | `&amp;` | | `quo.` | `/&quo.;/g` | `&quot;` | | `apo.` | `/&apo.;/g` | `&apos;` | PoC ```js const { XMLParser } = require("fast-xml-parser"); const xml = ` "> ]> Hello &lt;b&gt;World&lt;/b&gt; `; const result = new XMLParser().parse(xml); console.log(result.root.text); // Hello b>World/b> ``` No special parser options needed - `processEntities: true` is the default. When an app renders `result.root.text` in a page (e.g. `innerHTML`, template interpolation, SSR), the injected `` fires. `&amp;` can be shadowed too: ```js const xml2 = ` ]> SELECT * FROM t WHERE name='O&amp;Brien'`; const r = new XMLParser().parse(xml2); console.log(r.root); // SELECT * FROM t WHERE name='O'; DROP TABLE users;--Brien' ``` Impact This is a complete bypass of XML entity encoding. Any application that parses untrusted XML and uses the output in HTML, SQL, or other injection-sensitive contexts is affected. • Default config, no special options • Attacker can replace any `&lt;` / `&gt;` / `&amp;` / `&quot;` / `&apos;` with arbitrary strings • Direct XSS vector when parsed XML content is rendered in a page • v5 and v6 both affected Suggested fix Escape regex metacharacters before constructing the replacement regex: ```js const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); entities[entityName] = { regx: RegExp(`&${escaped};`, "g"), val: val }; ``` For v6, add `.` to the blacklist in `validateEntityName`: ```js const specialChar = "!?\\/[].{}^&*()<>|+"; ``` Severity CWE-185 (Incorrect Regular Expression) CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:H/A:N - 9.3 (CRITICAL) Entity decoding is a fundamental trust boundary in XML processing. This completely undermines it with no preconditions.

Related

Alias · CVE (1)

  • CVE-2026-25896 fast-xml-parser allows users to validate XML, parse XML to JS object, or build XML from JS object without C/C++ based libraries and no… vulnerability

Weakness · CWE (1)

  • CWE-185 Incorrect Regular Expression weakness

References