fast-xml-parser has an entity encoding bypass via regex injection in DOCTYPE entity names
Description
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 callback. From 4.1.3to before 5.3.5, 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 (<, >, &, ", ') with arbitrary values. This bypasses entity encoding and leads to XSS when parsed output is rendered. This vulnerability is fixed in 5.3.5.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
fast-xml-parsernpm | >= 5.0.0, < 5.3.5 | 5.3.5 |
fast-xml-parsernpm | >= 4.1.3, < 4.5.4 | 4.5.4 |
Affected products
1- Range: >= 5.0.0, < 5.3.5
Patches
2943ef0eb1b2dfix: Escape regex char in entity name
1 file changed · +2 −1
src/xmlparser/OrderedObjParser.js+2 −1 modified@@ -77,8 +77,9 @@ function addExternalEntities(externalEntities){ const entKeys = Object.keys(externalEntities); for (let i = 0; i < entKeys.length; i++) { const ent = entKeys[i]; + const escaped = ent.replace(/[.\-+*:]/g, '\\.'); this.lastEntities[ent] = { - regex: new RegExp("&"+ent+";","g"), + regex: new RegExp("&"+escaped+";","g"), val : externalEntities[ent] } }
ddcd0acf26ddEscape regex char in entity name
2 files changed · +11 −7
src/v6/EntitiesParser.js+7 −5 modified@@ -37,12 +37,13 @@ export default class EntitiesParser{ } addExternalEntity(key,val){ validateEntityName(key); + const escaped = key.replace(/[.\-+*:]/g, '\\.'); if(val.indexOf("&") !== -1) { reportWarning(`Entity ${key} is not added as '&' is found in value;`) return; }else{ - this.lastEntities[ent] = { - regex: new RegExp("&"+key+";","g"), + this.lastEntities[key] = { + regex: new RegExp("&"+escaped+";","g"), val : val } } @@ -52,8 +53,9 @@ export default class EntitiesParser{ const entKeys = Object.keys(entities); for (let i = 0; i < entKeys.length; i++) { const ent = entKeys[i]; + const escaped = ent.replace(/[.\-+*:]/g, '\\.'); this.docTypeEntities[ent] = { - regex: new RegExp("&"+ent+";","g"), + regex: new RegExp("&"+escaped+";","g"), val : entities[ent] } } @@ -89,11 +91,11 @@ export default class EntitiesParser{ } return val; } -}; +} //an entity name should not contains special characters that may be used in regex //Eg !?\\\/[]$%{}^&*()<> -const specialChar = "!?\\\/[]$%{}^&*()<>|+"; +const specialChar = "!?\\/[]$%{}^&*()<>|+"; function validateEntityName(name){ for (let i = 0; i < specialChar.length; i++) {
src/xmlparser/DocTypeReader.js+4 −2 modified@@ -25,11 +25,13 @@ export default class DocTypeReader{ i += 7; let entityName, val; [entityName, val,i] = this.readEntityExp(xmlData,i+1,this.suppressValidationErr); - if(val.indexOf("&") === -1) //Parameter entities are not supported + if(val.indexOf("&") === -1){ //Parameter entities are not supported + const escaped = entityName.replace(/[.\-+*:]/g, '\\.'); entities[ entityName ] = { - regx : RegExp( `&${entityName};`,"g"), + regx : RegExp( `&${escaped};`,"g"), val: val }; + } } else if( hasBody && hasSeq(xmlData, "!ELEMENT",i)) { i += 8;//Not supported
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
6- github.com/advisories/GHSA-m7jm-9gc2-mpf2ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-25896ghsaADVISORY
- github.com/NaturalIntelligence/fast-xml-parser/commit/943ef0eb1b2d3284e72dd74f44a042ee9f07026eghsax_refsource_MISCWEB
- github.com/NaturalIntelligence/fast-xml-parser/commit/ddcd0acf26ddd682cb0dc15a2bd6aa3b96bb1e69ghsax_refsource_MISCWEB
- github.com/NaturalIntelligence/fast-xml-parser/releases/tag/v5.3.5ghsax_refsource_MISCWEB
- github.com/NaturalIntelligence/fast-xml-parser/security/advisories/GHSA-m7jm-9gc2-mpf2ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.