Back to Blog
medium SEVERITY5 min read

How XML Entity Expansion Denial of Service happens in Node.js and how to fix it

A critical denial of service vulnerability (CVE-2026-33036) was discovered in fast-xml-parser versions prior to 5.5.6 and 4.5.5, allowing attackers to bypass entity expansion limits and crash Node.js applications through malicious XML payloads. This fix upgrades the dependency in the scripts directory to patched versions, protecting build pipelines and any runtime XML processing from resource exhaustion attacks.

O
By Orbis AppSec
Published August 5, 2026Reviewed August 5, 2026

Answer Summary

CVE-2026-33036 is a high-severity XML Entity Expansion (Billion Laughs) denial of service vulnerability in fast-xml-parser for Node.js, mapped to CWE-776. Attackers can craft XML documents that bypass entity expansion protections, causing exponential memory consumption and application crashes. The fix is to upgrade fast-xml-parser to version 5.5.6 or 4.5.5, which properly enforces entity expansion limits.

Vulnerability at a Glance

cweCWE-776
fixUpgrade fast-xml-parser to version 5.5.6 or 4.5.5
riskApplication crash and resource exhaustion via malicious XML
languageJavaScript (Node.js)
root causeInsufficient entity expansion limits in fast-xml-parser < 5.5.6
vulnerabilityXML Entity Expansion Denial of Service

Introduction

In the scripts/package-lock.json file, the build pipeline depended on fast-xml-parser version 5.3.4—a popular XML parsing library used across thousands of Node.js projects. However, Trivy security scanner flagged this dependency for CVE-2026-33036, a high-severity vulnerability that allows attackers to bypass XML entity expansion protections and trigger denial of service conditions.

The scripts/lib/larkImageDownloader.js file and related build tooling process external data, making this vulnerability particularly concerning. While the exact reachability wasn't confirmed, the presence of a vulnerable XML parser in the dependency tree creates unnecessary risk, especially in CI/CD environments where build scripts process various input formats.

The Vulnerability Explained

What is XML Entity Expansion?

XML Entity Expansion, commonly known as the "Billion Laughs" attack or XML bomb, exploits how XML parsers handle entity definitions. In XML, you can define entities that reference other entities, creating a nested structure:

<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  <!-- ... continues nesting ... -->
]>
<root>&lol9;</root>

When parsed, this small document expands exponentially—a few kilobytes of XML can expand to gigabytes of memory, crashing the application.

The Specific Vulnerability in fast-xml-parser

CVE-2026-33036 reveals that fast-xml-parser versions before 5.5.6 (and 4.5.5 for the 4.x branch) contained a bypass in their entity expansion protections. Even when developers configured limits, attackers could craft XML payloads that circumvented these safeguards.

The vulnerable version in scripts/package-lock.json:

{
  "fast-xml-parser": {
    "version": "5.3.4"
  }
}

Attack Scenario for This Codebase

Consider the build scripts in this repository. The scripts/lib/larkImageDownloader.js handles external integrations with services like Figma and AWS. If any part of the build pipeline processes XML responses—configuration files, API responses, or asset metadata—an attacker could:

  1. Compromise an upstream data source to inject malicious XML
  2. Submit a pull request with a malicious XML configuration file
  3. Manipulate cached responses in the CI/CD environment

The result? Build pipelines crash, deployments stall, and developer productivity grinds to a halt. In severe cases, this could be used as part of a larger attack to create windows of opportunity while teams scramble to restore services.

The Fix

Dependency Upgrade

The fix upgrades fast-xml-parser to version 5.5.6, which properly enforces entity expansion limits. The changes span the dependency management files:

Before (vulnerable):

// scripts/package-lock.json
"fast-xml-parser": {
  "version": "5.3.4"
}

After (patched):

// scripts/package-lock.json
"fast-xml-parser": {
  "version": "5.5.6"
}

New Dependencies for Enhanced Parsing

The fix also introduces supporting packages that fast-xml-parser 5.5.6 relies on for safer parsing:

"node_modules/@nodable/entities": {
  "version": "3.0.0",
  "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-3.0.0.tgz",
  "integrity": "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw=="
}
"node_modules/anynum": {
  "version": "1.0.1",
  "resolved": "https://registry.npmjs.org/anynum/-/anynum-1.0.1.tgz",
  "integrity": "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A=="
}

These packages provide improved entity handling and numeric parsing that support the security fixes in the new fast-xml-parser version.

Yarn Configuration Updates

The fix also adds Yarn configuration (.yarnrc.yml) to ensure consistent dependency resolution:

approvedGitRepositories:
  - "**"

nodeLinker: node-modules

npmMinimalAgeGate: 0

This ensures the patched version is consistently installed across all environments, preventing accidental downgrades.

Prevention & Best Practices

1. Keep XML Parsers Updated

XML vulnerabilities are discovered regularly. Implement automated dependency scanning:

# Using npm audit
npm audit

# Using Trivy
trivy fs --scanners vuln .

2. Configure Parser Limits Explicitly

Even with patched versions, configure defensive limits:

const { XMLParser } = require('fast-xml-parser');

const parser = new XMLParser({
  allowBooleanAttributes: true,
  // Explicitly limit entity expansion
  processEntities: false, // Disable if not needed
  // Or configure strict limits if entities are required
});

3. Validate and Sanitize XML Input

Before parsing, validate XML against expected schemas:

// Reject suspiciously large XML documents
const MAX_XML_SIZE = 1024 * 1024; // 1MB

function parseXMLSafely(xmlString) {
  if (xmlString.length > MAX_XML_SIZE) {
    throw new Error('XML document exceeds size limit');
  }

  // Check for entity declarations
  if (xmlString.includes('<!ENTITY')) {
    throw new Error('XML entity declarations not allowed');
  }

  return parser.parse(xmlString);
}

4. Use Dependency Lock Files

Always commit lock files (package-lock.json, yarn.lock) to ensure reproducible builds with known-good versions.

5. Implement Security Scanning in CI/CD

Add security scanning to your pipeline:

# Example GitHub Actions workflow
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    scan-type: 'fs'
    scan-ref: '.'
    severity: 'HIGH,CRITICAL'

Key Takeaways

  • fast-xml-parser < 5.5.6 allows entity expansion bypass: Even configured limits could be circumvented, making all XML parsing potentially vulnerable to DoS
  • Build scripts are attack surfaces too: The scripts/ directory processes external data through Figma and AWS integrations—vulnerable dependencies here affect your entire CI/CD pipeline
  • Dependency sub-trees matter: The vulnerability was in scripts/package-lock.json, not the main application—scan all package manifests in your repository
  • Entity expansion differs from XXE: Disabling external entities doesn't protect against internal entity expansion attacks; you need explicit expansion limits
  • Automated scanning catches what manual review misses: Trivy identified this CVE in the dependency tree before it could be exploited

How Orbis AppSec Detected This

  • Source: XML data processed by fast-xml-parser in the scripts dependency tree
  • Sink: fast-xml-parser parse functions that expand XML entities without proper limits
  • Missing control: Entity expansion depth and size limits were bypassable in version 5.3.4
  • CWE: CWE-776 (Improper Restriction of Recursive Entity References in DTDs)
  • Fix: Upgraded fast-xml-parser from 5.3.4 to 5.5.6, which properly enforces entity expansion limits

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-33036 in fast-xml-parser demonstrates why dependency management is a critical security practice. Even well-maintained libraries can have vulnerabilities, and XML parsing has been a persistent source of security issues for decades. By upgrading to fast-xml-parser 5.5.6, this codebase now has proper protection against entity expansion attacks.

Remember: your build scripts and development tooling are part of your attack surface. A compromised CI/CD pipeline can lead to supply chain attacks affecting all downstream users. Keep all dependencies updated, scan regularly, and treat every XML parser configuration as security-sensitive code.

References

Frequently Asked Questions

What is XML Entity Expansion?

XML Entity Expansion (also called the Billion Laughs attack) is a denial of service technique where nested XML entities exponentially expand when parsed, consuming excessive memory and CPU resources.

How do you prevent XML Entity Expansion in Node.js?

Use XML parsers with built-in entity expansion limits, keep dependencies updated, disable DTD processing when not needed, and set explicit limits on entity expansion depth and size.

What CWE is XML Entity Expansion?

XML Entity Expansion is classified as CWE-776: Improper Restriction of Recursive Entity References in DTDs ('XML Entity Expansion').

Is disabling external entities enough to prevent XML Entity Expansion?

No, disabling external entities (XXE protection) doesn't prevent internal entity expansion attacks. You need explicit limits on entity expansion depth and total expansion size.

Can static analysis detect XML Entity Expansion vulnerabilities?

Yes, tools like Trivy, Snyk, and Dependabot can detect vulnerable XML parser versions. Static analyzers can also flag XML parsing code that lacks proper configuration.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #3607

Related Articles

critical

How Arbitrary Code Execution via Command Injection Happens in Node.js shell-quote and How to Fix It

A critical command injection vulnerability (CVE-2026-9277) was discovered in the popular Node.js `shell-quote` package (versions prior to 1.8.4) where unescaped line terminators allowed attackers to inject and execute arbitrary shell commands. The fix upgrades `shell-quote` from version 1.8.1 to 1.8.4, which properly escapes line terminator characters (such as `\n`, `\r`, `\u2028`, and `\u2029`) before passing strings to the shell. This dependency was present in the project's `package-lock.json`

critical

How ReDoS Vulnerabilities Happen in Node.js Express Applications and How to Fix Them

A critical Regular Expression Denial of Service (ReDoS) vulnerability in the path-to-regexp package (CVE-2024-45296) was discovered in the lacartoons-addon project's dependency tree. The vulnerable versions used backtracking regular expressions that could cause catastrophic performance degradation when processing malicious route patterns. Upgrading to patched versions (0.1.10 for Express's internal router) eliminates this attack vector.

high

How Denial of Service via Exponential Time Complexity happens in brace-expansion and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-13149) was discovered in the brace-expansion npm package, where specially crafted input patterns could trigger exponential time complexity, potentially freezing Node.js applications. The fix upgrades multiple versions of brace-expansion (1.1.18 → 1.1.16, 2.1.1 → 2.1.2, and 5.0.6 → 5.0.7) through yarn resolutions to ensure all dependency paths use patched versions.

high

How Remote Code Execution via serialize-javascript happens in Node.js and how to fix it

The `serialize-javascript` package version 6.0.2 contained a high-severity Remote Code Execution (RCE) vulnerability (GHSA-5c6j-r48x-rmvq) exploitable through crafted `RegExp.flags` and `Date.prototype.toISOString()` payloads. Upgrading to version 7.0.3 eliminates the vulnerable serialization logic and removes the `randombytes` dependency that was part of the attack surface. This fix was applied via a `package.json` override and `package-lock.json` update.

critical

How unvalidated URL input handling happens in SvelteKit with Tauri and how to fix it

A critical vulnerability in `src/routes/+page.svelte` allowed attackers to supply arbitrary URLs—including `http://` and local file paths—through query parameters and drag-drop events, which were then fetched without validation. The fix restricts input to HTTPS-only URLs and removes the dangerous local file fetch path entirely, eliminating both SSRF and local file disclosure attack vectors.

medium

How OAuth token audience bypass happens in Node.js serverless functions and how to fix it

A critical OAuth authentication vulnerability in a Netlify serverless function allowed any valid Google OAuth token—even those issued to completely different applications—to authenticate successfully. The fix adds proper audience (aud) claim verification using Google's tokeninfo endpoint to ensure only tokens issued specifically for this application are accepted.