Jul 22, 2026·8 min read·3 visits
Unauthenticated remote attackers can cause denial of service and crash fast-xml-parser applications by using repeated DOCTYPE declarations to bypass XML entity expansion limits.
A Denial of Service (DoS) vulnerability has been identified in the Node.js XML parsing library fast-xml-parser. The flaw allows unauthenticated remote attackers to cause severe CPU exhaustion, event-loop blocking, and system crashes by sending a crafted XML payload containing repeated DOCTYPE declarations that bypass recursive entity expansion protections.
The fast-xml-parser library is a widely utilized Node.js package designed for parsing XML data into JavaScript objects. It is frequently employed in high-throughput APIs and web services where quick parsing speeds are required. The library supports custom Document Type Definitions (DTDs) and XML entity processing, making it vulnerable to standard parser risks if inputs are not properly restricted.
A denial-of-service vulnerability, tracked as GHSA-8r6m-32jq-jx6q, exists in versions 5.9.3 through 5.10.0 of fast-xml-parser. This flaw allows remote, unauthenticated attackers to exhaust system resources by bypassing built-in entity expansion limits. Because the Node.js runtime is single-threaded, resource-intensive operations in the XML parser can completely block the event loop, rendering the host application unresponsive.
This vulnerability stems from the parser's failure to restrict the number of DOCTYPE declarations processed within a single XML payload. By interleaving dummy DOCTYPE definitions, an attacker can repeatedly reset the internal counters used to track recursive entity expansion. This lets the payload execute a successful XML entity expansion attack, commonly referred to as an "XML bomb" or "Billion Laughs" attack.
The core issue resides in the coordination between fast-xml-parser and its dependency @nodable/entities during custom entity extraction. When the parser encounters a <!DOCTYPE declaration, it extracts the declared entities and registers them using the addInputEntities() function. This function initializes the entity expansion limits and sets up protection mechanisms to guard against exponential nested expansion.
To prevent unbounded CPU and memory consumption, the parser tracks expansion progress via state variables like entityExpansionCount and currentExpandedLength. Under standard operations, if these variables exceed the configured threshold during the evaluation of recursive entities, the parser throws an exception to abort execution. This is the primary defense against CWE-776 (Improper Restriction of Recursive Entity References in DTDs).
However, every invocation of addInputEntities() resets these internal protection counters back to zero. The parser did not restrict the number of times a DOCTYPE declaration could appear in a single document. By introducing multiple DOCTYPE statements throughout the XML structure, an attacker can force the parser to call addInputEntities() repeatedly.
As a result, each subsequent DOCTYPE declaration wipes out the accumulated tracking metrics. The safety threshold is never reached because the expansion tracker is reset before it can detect the cumulative threat. The parsing logic is thus deceived into treating an exponentially expanding entity tree as a series of safe, isolated entity declarations.
To understand the mechanics of the vulnerability and its remediation, we examine the changes introduced in commit 4e546e03987662de5495d050b5fba26bea65383f within the file src/xmlparser/OrderedObjParser.js.
The patch addresses the vulnerability by enforcing a strict constraint: an XML document must contain at most one DOCTYPE declaration. The tracking state is maintained using a new boolean property, doctypefound.
Below is a structured representation of the parsing flow during a multiple DOCTYPE attack:
The vulnerable version of OrderedObjParser.js did not define or check a state flag for DOCTYPE declarations. Let us compare the vulnerable logic with the patched code:
// Vulnerable Implementation (Before Commit 4e546e0)
// The parser continuously processes DOCTYPE tokens without tracking state.
} else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 68) { // '!D'
const result = docTypeReader.readDocType(xmlData, i);
this.entityDecoder.addInputEntities(result.entities);
i = result.i;
}In the vulnerable implementation, each encounter with !D immediately calls addInputEntities(), resetting the safety state in @nodable/entities. The patched implementation mitigates this by tracking occurrences of the DOCTYPE token:
// Patched Implementation (After Commit 4e546e0)
// A tracking variable enforces the single DOCTYPE constraint.
export default class OrderedObjParser {
constructor(options) {
this.entityExpansionCount = 0;
this.currentExpandedLength = 0;
this.doctypefound = false; // Initialize state variable
}
}
const parseXml = function (xmlData) {
this.entityExpansionCount = 0;
this.currentExpandedLength = 0;
this.doctypefound = false; // Reset state variable at start of parsing
// ...
}
// Inside token loop
} else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 68) { // '!D'
if (this.doctypefound) {
throw new Error("Multiple DOCTYPE declarations found."); // Reject duplicate DOCTYPEs
}
this.doctypefound = true;
const result = docTypeReader.readDocType(xmlData, i);
this.entityDecoder.addInputEntities(result.entities);
i = result.i;
}While this patch effectively resolves the immediate attack vector, a minor architectural limitation remains. The character scanner searches specifically for the uppercase ASCII characters representing <!D. If the downstream XML parsing architecture allows HTML5-style case-insensitive <!doctype strings under permissive execution modes, there is a risk that different code paths could bypass this exact check. Developers should verify that custom parser instances do not run in permissive environments that tolerate non-standard casing.
Exploiting this vulnerability requires the ability to send custom XML payloads to an endpoint that parses the input using fast-xml-parser with entity processing enabled. No authentication is required to perform this action. The attacker must construct a payload that blends recursively defined XML entities with multiple DOCTYPE statements.
A conceptual exploit payload uses intermediate DOCTYPE declarations to reset the safety limit counters. Each block defines a set of entities that expand exponentially when referenced. The interleaving declarations ensure that the recursive expansion limits are continually reset before the system detects an XML bomb:
<!DOCTYPE root [
<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
]>
<!-- Intermediate DOCTYPE to reset the expansion counters -->
<!DOCTYPE reset1 [
<!ENTITY dummy "1">
]>
<!DOCTYPE root2 [
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
]>
<!-- Second reset to bypass subsequent depth thresholds -->
<!DOCTYPE reset2 [
<!ENTITY dummy "2">
]>
<!DOCTYPE root3 [
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
]>
<root>&lol3;</root>When this payload is submitted, the parser begins evaluating &lol3;. It expands into ten lol2 entities, which further expand into lol1, and eventually into the base lol literal. Due to the reset directives, the parsing engine allows the recursive depth to reach exponential proportions.
The consequence of this expansion is severe. The Node.js application process runs on a single event-loop thread. The intense computational demand of resolving billions of nested strings consumes 100% of the host CPU, blocking the event loop and preventing the application from serving other concurrent requests. Eventually, the process exhausts its allocated heap memory and is terminated by the operating system kernel with an Out Of Memory (OOM) error.
The impact of GHSA-8r6m-32jq-jx6q is categorized as high for availability. Successful exploitation allows an unauthenticated remote attacker to completely disrupt the availability of the host service. Because Node.js services are typically deployed as single-threaded processes, blocking the event loop for one client blocks all other users.
Although confidentiality and integrity are not directly impacted, the denial-of-service condition can be weaponized in multi-stage attack scenarios. Attackers can use application crashes to disable security logging systems, disrupt real-time monitoring solutions, or create windows of opportunity for subsequent network attacks.
The vulnerability does not result in remote code execution or data exposure, which limits its impact to system availability. Consequently, the CVSS v4.0 score is calculated as 8.7 (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N). This high severity reflects the ease of exploitation and the direct path to service denial.
The primary remediation strategy is upgrading the fast-xml-parser package to version 5.10.1 or later. This patch closes the vulnerability by rejecting payloads that contain multiple DOCTYPE declarations.
To execute the upgrade via npm, run the following command in the project directory:
npm install fast-xml-parser@5.10.1If an immediate upgrade is not feasible, security administrators can apply temporary workarounds. The most robust workaround is to disable entity processing entirely. This can be achieved by ensuring that the processEntities configuration parameter is omitted or set to false:
const { XMLParser } = require("fast-xml-parser");
const options = {
processEntities: false // Disables custom entity resolution
};
const parser = new XMLParser(options);Additionally, input validation filters can be introduced at the reverse proxy or API gateway layers. Administrators can deploy regular-expression checks to inspect incoming payload bodies and reject requests that contain more than one occurrence of <!DOCTYPE:
function preValidateXml(rawBody) {
const matches = rawBody.match(/<!DOCTYPE/gi);
if (matches && matches.length > 1) {
throw new Error("Invalid request: Multiple DOCTYPE declarations are prohibited.");
}
}CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
fast-xml-parser NaturalIntelligence | >= 5.9.3, < 5.10.1 | 5.10.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-776 / CWE-400 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 8.7 (High) |
| Exploit Status | Proof of Concept (PoC) available |
| KEV Status | Not listed on CISA KEV |
| Impact | Denial of Service (DoS) / Single-Thread Blocking |
The product does not properly restrict recursive entity references in Document Type Definitions (DTDs), making it vulnerable to XML Entity Expansion attacks.
An issue in rails-html-sanitizer allowed attackers to bypass restrictions on SVG reference elements (such as <use> or <feImage>) when specific custom configurations allowed these tags. Because the sanitizer only restricted the legacy 'xlink:href' attribute to local references, modern browsers supporting plain 'href' attributes according to the SVG 2 specification would load external resources. This could lead to Cross-Site Scripting (XSS) or user tracking.
An input validation flaw in GitPython allows remote attackers to exfiltrate system environment variables and bypass safe-protocol restrictions via crafted repository URLs passed to the clone API.
The high-performance Node.js image processing library sharp inherits several high and medium-severity security vulnerabilities from its underlying native dependency libvips. These include integer overflows in dimensions calculation, heap-based buffer overflows in GIF/TIFF and JPEG2000 processing, and out-of-bounds reads in the EXIF directory decoder, enabling denial of service and potential code execution.
An interpretation conflict (CWE-436) exists in fast-uri due to differing handling of backslash characters between RFC 3986 and the WHATWG URL specification. This differential allows remote attackers to bypass SSRF filters and origin-allowlist protections when fast-uri is used in conjunction with WHATWG-compliant HTTP clients like Node.js native fetch or undici.
An authorization bypass vulnerability exists in FasterXML jackson-databind versions 2.18.x up to 2.18.8 (and other release branches) where the active @JsonView constraint is bypassed during the deserialization of properties marked with @JsonUnwrapped. This allows remote, authenticated attackers to alter restricted administrative properties on server-side objects by injecting flattened parameters into standard JSON payloads.
CVE-2026-58426 is a critical security vulnerability in Gitea Actions where improper signature serialization allows an authenticated attacker to execute a canonicalization (boundary-shifting) attack. By rewriting query parameters while keeping the signature intact, the attacker can bypass access control checks to read private workflow artifacts or modify concurrent task upload states.