VYPR
High severityOSV Advisory· Published Jan 30, 2026· Updated Feb 11, 2026

fast-xml-parser has RangeError DoS Numeric Entities Bug

CVE-2026-25128

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. In versions 5.0.9 through 5.3.3, a RangeError vulnerability exists in the numeric entity processing of fast-xml-parser when parsing XML with out-of-range entity code points (e.g., � or �). This causes the parser to throw an uncaught exception, crashing any application that processes untrusted XML input. Version 5.3.4 fixes the issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
fast-xml-parsernpm
>= 5.0.9, < 5.3.45.3.4

Affected products

1

Patches

1
4e387f61c4a5

handle html entities when out of range

https://github.com/NaturalIntelligence/fast-xml-parseramit kumar guptaJan 30, 2026via ghsa
3 files changed · +39 97
  • spec/entities_spec.js+22 0 modified
    @@ -433,6 +433,28 @@ describe("XMLParser Entities", function() {
             expect(result).toEqual(expected);
         });
     
    +    it("should skip HTML numeric or hex entities when htmlEntities:true but entity is out of range", function() {
    +        const xmlData = `<root attr="&#9999999;">&#xFFFFFF;</root>`;
    +
    +        const expected = {
    +            "root": {
    +                "#text": "&#xFFFFFF;",
    +                "attr": "&#9999999;"
    +            }
    +        };
    +
    +        const options = {
    +            attributeNamePrefix: "",
    +            ignoreAttributes:    false,
    +            processEntities: true,
    +            htmlEntities: true,
    +        };
    +        const parser = new XMLParser(options);
    +        let result = parser.parse(xmlData);
    +
    +        expect(result).toEqual(expected);
    +    });
    +
         it("should throw error if an entity name contains special char", function() {
             const xmlData = `
             <?xml version="1.0" encoding="UTF-8"?>
    
  • spec/temp.js+5 95 modified
    @@ -4,104 +4,14 @@ import { format } from "path";
     import {XMLParser, XMLValidator, XMLBuilder} from "../src/fxp.js";
     
     describe("unpaired and empty tags", function() {
    -    xit("bug test", function() {
    +    fit("bug test", function() {
             
    -        const xmlData = `<?xml version="1.0"?>
    -<!DOCTYPE softwarelists [
    -<!ELEMENT softwarelists (softwarelist*)>
    -	<!ELEMENT softwarelist (notes?, software+)>
    -		<!ATTLIST softwarelist name CDATA #REQUIRED>
    -		<!ATTLIST softwarelist description CDATA #IMPLIED>
    -		<!ELEMENT notes (#PCDATA)>
    -		<!ELEMENT software (description, year, publisher, notes?, info*, sharedfeat*, part*)>
    -			<!ATTLIST software name CDATA #REQUIRED>
    -			<!ATTLIST software cloneof CDATA #IMPLIED>
    -			<!ATTLIST software supported (yes|partial|no) "yes">
    -			<!ELEMENT description (#PCDATA)>
    -			<!ELEMENT year (#PCDATA)>
    -			<!ELEMENT publisher (#PCDATA)>
    -			<!ELEMENT notes (#PCDATA)>
    -			<!ELEMENT info EMPTY>
    -				<!ATTLIST info name CDATA #REQUIRED>
    -				<!ATTLIST info value CDATA #IMPLIED>
    -			<!ELEMENT sharedfeat EMPTY>
    -				<!ATTLIST sharedfeat name CDATA #REQUIRED>
    -				<!ATTLIST sharedfeat value CDATA #IMPLIED>
    -			<!ELEMENT part (feature*, dataarea*, diskarea*, dipswitch*)>
    -				<!ATTLIST part name CDATA #REQUIRED>
    -				<!ATTLIST part interface CDATA #REQUIRED>
    -				<!ELEMENT feature EMPTY>
    -					<!ATTLIST feature name CDATA #REQUIRED>
    -					<!ATTLIST feature value CDATA #IMPLIED>
    -				<!ELEMENT dataarea (rom*)>
    -					<!ATTLIST dataarea name CDATA #REQUIRED>
    -					<!ATTLIST dataarea size CDATA #REQUIRED>
    -					<!ATTLIST dataarea databits (8|16|32|64) "8">
    -					<!ATTLIST dataarea endian (big|little) "little">
    -					<!ELEMENT rom EMPTY>
    -						<!ATTLIST rom name CDATA #IMPLIED>
    -						<!ATTLIST rom size CDATA #IMPLIED>
    -						<!ATTLIST rom length CDATA #IMPLIED>
    -						<!ATTLIST rom crc CDATA #IMPLIED>
    -						<!ATTLIST rom sha1 CDATA #IMPLIED>
    -						<!ATTLIST rom offset CDATA #IMPLIED>
    -						<!ATTLIST rom value CDATA #IMPLIED>
    -						<!ATTLIST rom status (baddump|nodump|good) "good">
    -						<!ATTLIST rom loadflag (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload|fill|continue|reload_plain) #IMPLIED>
    -				<!ELEMENT diskarea (disk*)>
    -					<!ATTLIST diskarea name CDATA #REQUIRED>
    -					<!ELEMENT disk EMPTY>
    -						<!ATTLIST disk name CDATA #REQUIRED>
    -						<!ATTLIST disk sha1 CDATA #IMPLIED>
    -						<!ATTLIST disk status (baddump|nodump|good) "good">
    -						<!ATTLIST disk writeable (yes|no) "no">
    -				<!ELEMENT dipswitch (dipvalue*)>
    -					<!ATTLIST dipswitch name CDATA #REQUIRED>
    -					<!ATTLIST dipswitch tag CDATA #REQUIRED>
    -					<!ATTLIST dipswitch mask CDATA #REQUIRED>
    -					<!ELEMENT dipvalue EMPTY>
    -						<!ATTLIST dipvalue name CDATA #REQUIRED>
    -						<!ATTLIST dipvalue value CDATA #REQUIRED>
    -						<!ATTLIST dipvalue default (yes|no) "no">
    -]>
    -
    -<softwarelists>
    -	<softwarelist name="snes" description="Nintendo SNES cartridges">
    -		<software name="aokidenp" cloneof="aokiden">
    -			<description>Aoki Densetsu Shoot! (Japan, prototype)</description>
    -			<year>1994</year>
    -			<publisher>KSS</publisher>
    -			<info name="alt_title" value="蒼き伝説シュート!"/>
    -			<part name="cart" interface="snes_cart">
    -				<feature name="battery" value="BATT CR2032" />
    -				<feature name="cart_model" value="no shell" />
    -				<feature name="lockout" value="" />
    -				<feature name="pcb" value="SHVC-4PV5B-01" />
    -				<feature name="slot" value="lorom" />
    -				<feature name="u1" value="U1 EPROM" />
    -				<feature name="u2" value="U2 EPROM" />
    -				<feature name="u3" value="U3 EPROM" />
    -				<feature name="u4" value="U4 EPROM" />
    -				<feature name="u5" value="U5 SRAM" />
    -				<feature name="u6" value="U6 PLD" />
    -				<feature name="u7" value="U7 74LS157" />
    -				<feature name="u8" value="U8 CIC" />
    -				<dataarea name="rom" size="1572864">
    -					<rom name="shoot 1 kss.u1" size="524288" crc="71306e06" sha1="253ec028d68a85209dc3e5846a2a2f5b582fed7b"/>
    -					<rom name="shoot 2 kss.u2" size="524288" crc="d07e1be3" sha1="7a58acb027ca15c1054e58f43156c2d99f62d16c"/>
    -					<rom name="shoot 3 kss.u3" size="524288" crc="380ed94f" sha1="8607ce31748ae73b9aa7aacda80c843622c61a79"/>
    -				</dataarea>
    -				<dataarea name="nvram" size="131072">
    -				</dataarea>
    -			</part>
    -		</software>
    -	</softwarelist>
    -</softwarelists>
    -
    -`;
    +        const xmlData = `<root attr="&#9999999;"/>`;
             const options = {
                 ignoreAttributes: false,
                 attributeNamePrefix: '',
    +						//processEntities: true, 
    +						htmlEntities: true 
             };
             const parser = new XMLParser(options);
             // console.log(JSON.stringify(parser.parse(xml)));
    @@ -112,7 +22,7 @@ describe("unpaired and empty tags", function() {
             // expect(result).toEqual(expected);
     
         });
    -    fit("bug test", function() {
    +    xit("bug test", function() {
             
             const xmlData = `<?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE dmodule [
    
  • src/xmlparser/OrderedObjParser.js+12 2 modified
    @@ -41,8 +41,8 @@ export default class OrderedObjParser{
           "copyright" : { regex: /&(copy|#169);/g, val: "©" },
           "reg" : { regex: /&(reg|#174);/g, val: "®" },
           "inr" : { regex: /&(inr|#8377);/g, val: "₹" },
    -      "num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCodePoint(Number.parseInt(str, 10)) },
    -      "num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCodePoint(Number.parseInt(str, 16)) },
    +      "num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => fromCodePoint(str, 10, "&#") },
    +      "num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => fromCodePoint(str, 16, "&#x") },
         };
         this.addExternalEntities = addExternalEntities;
         this.parseXml = parseXml;
    @@ -627,3 +627,13 @@ function parseValue(val, shouldParse, options) {
         }
       }
     }
    +
    +function fromCodePoint(str, base, prefix){
    +  const codePoint = Number.parseInt(str, base);
    +
    +  if (codePoint >= 0 && codePoint <= 0x10FFFF) {
    +      return String.fromCodePoint(codePoint);
    +  } else {
    +      return prefix +str + ";";
    +  }
    +}
    \ No newline at end of file
    

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

5

News mentions

0

No linked articles in our index yet.