VYPR
Low severityNVD Advisory· Published Feb 26, 2026· Updated Feb 26, 2026

fast-xml-parser has stack overflow in XMLBuilder with preserveOrder

CVE-2026-27942

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. Prior to version 5.3.8, the application crashes with stack overflow when user use XML builder with preserveOrder:true. Version 5.3.8 fixes the issue. As a workaround, use XML builder with preserveOrder:false or check the input data before passing to builder.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
fast-xml-parsernpm
>= 5.0.0, < 5.3.85.3.8
fast-xml-parsernpm
>= 4.0.0-beta.0, < 4.5.44.5.4

Affected products

1

Patches

1
c13a961910f1

handle non-array input for XML builder when preserveOrder is true

https://github.com/NaturalIntelligence/fast-xml-parseramit kumar guptaFeb 25, 2026via ghsa
2 files changed · +51 10
  • spec/j2x_ordered_spec.js+37 7 modified
    @@ -1,4 +1,5 @@
    -import {XMLParser, XMLBuilder} from "../src/fxp.js";
    +import { format } from "path";
    +import { XMLParser, XMLBuilder } from "../src/fxp.js";
     
     describe("XMLBuilder", function () {
     
    @@ -31,11 +32,11 @@ describe("XMLBuilder", function () {
             }
             const parser = new XMLParser(options);
             let result = parser.parse(XMLdata);
    -    // console.log(JSON.stringify(result, null,4));
    +        // console.log(JSON.stringify(result, null,4));
     
             const builder = new XMLBuilder(options);
             result = builder.build(result);
    -    // console.log(result);
    +        // console.log(result);
     
             expect(result).toEqual(expected);
         });
    @@ -65,16 +66,16 @@ describe("XMLBuilder", function () {
                 preserveOrder: true,
                 cdataPropName: "#CDATA",
                 allowBooleanAttributes: true,
    -    //   format: true,
    +            //   format: true,
     
             }
             const parser = new XMLParser(options);
             let result = parser.parse(XMLdata);
    -    // console.log(JSON.stringify(result, null,4));
    +        // console.log(JSON.stringify(result, null,4));
     
             const builder = new XMLBuilder(options);
             result = builder.build(result);
    -    // console.log(result);
    +        // console.log(result);
     
             expect(result).toEqual(expected);
         });
    @@ -300,7 +301,7 @@ describe("XMLBuilder", function () {
     
             const options = {
                 ignoreAttributes: false,
    -            isArray: (tagName, jpath, isLeafNode, isAttribute) => { 
    +            isArray: (tagName, jpath, isLeafNode, isAttribute) => {
                     if (isLeafNode === true) return true;
                 },
                 preserveOrder: true
    @@ -319,4 +320,33 @@ describe("XMLBuilder", function () {
             // console.log(result);
             expect(result).toEqual(expected);
         });
    +
    +
     });
    +
    +describe("XMLBuilder- array processing issue", function () {
    +    it("should not throw stack overflow when child value is a non-array (issue #781)", function () {
    +        const builder = new XMLBuilder({
    +            ignoreAttributes: false,
    +            attributeNamePrefix: '@_',
    +            preserveOrder: true,
    +        });
    +        const input = [
    +            {
    +                'foo': [
    +                    { 'bar': [{ '@_V': 'baz' }] },
    +                    //{ 'fum': [{ 'qux': '' }] },
    +                    { 'hello': [{ '#text': 'world' }] }
    +                ]
    +            }
    +        ];
    +        expect(function () {
    +            builder.build(input);
    +        }).not.toThrow();
    +
    +        const result = builder.build(input);
    +        expect(result).toContain('<hello>world</hello>');
    +        expect(result).toContain('<foo>');
    +    });
    +
    +});
    \ No newline at end of file
    
  • src/xmlbuilder/orderedJs2Xml.js+14 3 modified
    @@ -18,10 +18,21 @@ function arrToStr(arr, options, jPath, indentation) {
         let xmlStr = "";
         let isPreviousElementTag = false;
     
    +
    +    if (!Array.isArray(arr)) {
    +        // Non-array values (e.g. string tag values) should be treated as text content
    +        if (arr !== undefined && arr !== null) {
    +            let text = arr.toString();
    +            text = replaceEntitiesValue(text, options);
    +            return text;
    +        }
    +        return "";
    +    }
    +
         for (let i = 0; i < arr.length; i++) {
             const tagObj = arr[i];
             const tagName = propName(tagObj);
    -        if(tagName === undefined) continue;
    +        if (tagName === undefined) continue;
     
             let newJPath = "";
             if (jPath.length === 0) newJPath = tagName
    @@ -92,7 +103,7 @@ function propName(obj) {
         const keys = Object.keys(obj);
         for (let i = 0; i < keys.length; i++) {
             const key = keys[i];
    -        if(!obj.hasOwnProperty(key)) continue;
    +        if (!obj.hasOwnProperty(key)) continue;
             if (key !== ":@") return key;
         }
     }
    @@ -101,7 +112,7 @@ function attr_to_str(attrMap, options) {
         let attrStr = "";
         if (attrMap && !options.ignoreAttributes) {
             for (let attr in attrMap) {
    -            if(!attrMap.hasOwnProperty(attr)) continue;
    +            if (!attrMap.hasOwnProperty(attr)) continue;
                 let attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
                 attrVal = replaceEntitiesValue(attrVal, options);
                 if (attrVal === true && options.suppressBooleanAttributes) {
    

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.