Oct 3, 2026·7 min read·1 visit
Unauthenticated remote attackers can crash Node.js servers using @fastify/busboy by sending a multipart request with __proto__ or constructor in the headers, triggering an unhandled TypeError.
A critical remote, unauthenticated Denial of Service (DoS) vulnerability in @fastify/busboy (<= 3.2.0) allows attackers to crash the Node.js process. By submitting a crafted multipart/form-data request with a header key matching an inherited property of Object.prototype (like __proto__ or constructor), the internal HeaderParser triggers a synchronous TypeError.
The vulnerability CVE-2026-19481 describes a remote, unauthenticated Denial of Service (DoS) flaw within the @fastify/busboy multipart form-data parser for Node.js. This library serves as a critical infrastructure component, parsing streaming incoming data in numerous web applications and frameworks, including Fastify. The attack surface is exposed via any endpoint accepting HTTP POST or PUT requests formatted as multipart/form-data payloads.\n\nAt its core, the vulnerability resides in the integrated dicer component located at deps/dicer/lib/HeaderParser.js. This module parses the headers of incoming multipart boundaries sequentially. Because the parser utilizes standard plain JavaScript objects ({}) to temporarily store parsed headers, it remains susceptible to prototype property collision attacks.\n\nWhen a request contains a part header with a name that overlaps with built-in properties of Object.prototype, such as __proto__ or constructor, the internal dictionary lookup fails to distinguish between 'own properties' and inherited properties. This behavior leads to type confusion within the parser's logic. If an application does not catch the resulting synchronous error, the Node.js event loop terminates, resulting in a complete Denial of Service.
JavaScript objects instantiated via the literal notation {} inherit properties and methods directly from the global Object.prototype. These inherited properties include standard utility methods and internal pointers such as toString, valueOf, constructor, and __proto__. When an application performs a property lookup on a plain object, the JavaScript engine searches the object's own keys first, subsequently traversing the prototype chain if the key is not found.\n\nIn the vulnerable versions of @fastify/busboy (versions 1.0.0 through 3.2.0), the HeaderParser class processes multipart headers and aggregates duplicates into an array. It initializes its internal header storage dictionary using this.header = {}. When parsing each header line, the parser extracts the header name, converts it to lowercase, and performs a lookup operation: this.header[h] || (this.header[h] = []).\n\nIf the lowercase header key matches a property belonging to Object.prototype (for example, __proto__), the lookup expression evaluates to the built-in prototype object. The logical OR operator (||) short-circuits because Object.prototype is a truthy value, bypassing the array initialization branch. Consequently, the variable storing the header accumulation structure is assigned Object.prototype rather than a new empty array.\n\nImmediately following this lookup, the parser invokes the .push() method on the returned reference: values.push(...). Because Object.prototype does not implement a push method, the engine throws a synchronous TypeError. This uncaught exception propagates up the execution stack, aborting the asynchronous parsing thread and terminating the parent process.
To understand the structural failure, we analyze the vulnerable logic in deps/dicer/lib/HeaderParser.js. The initialization logic establishes a plain object cache, while the header parsing loop attempts to write incoming headers directly into this object without checking ownership:\n\njavascript\n// Vulnerable constructor initialization\nfunction HeaderParser (cfg) {\n // ...\n this.buffer = ''\n this.header = {} // Vulnerable plain object initialization\n this.finished = false\n this.tail = ''\n}\n\n// Vulnerable parser accumulator logic\nHeaderParser.prototype._parseHeader = function () {\n // ...\n h = buffer.slice(lineStart, posColon).toLowerCase()\n let valueStart = posColon + 1\n if (buffer[valueStart] === ' ' || buffer[valueStart] === '\\t') { ++valueStart }\n \n // If h is '__proto__', this.header[h] resolves to Object.prototype\n const values = this.header[h] || (this.header[h] = [])\n // This throws 'TypeError: values.push is not a function'\n values.push(buffer.slice(valueStart, lineEnd))\n // ...\n}\n\n\nThe official security patch (957a24b66d5915e6d0a6ac988c9dbcee86373e9b) resolves the vulnerability by implementing prototype-less objects via Object.create(null). These objects do not possess a link to Object.prototype and therefore contain zero inherited properties. The modified logic ensures that looking up __proto__ or constructor yields undefined, forcing the code to safely initialize a new array directly on the object as an 'own' property.\n\ndiff\n@@ -17,7 +17,7 @@ function HeaderParser (cfg) {\n this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000)\n this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024)\n this.buffer = ''\n- this.header = {}\n+ this.header = Object.create(null)\n this.finished = false\n this.tail = ''\n }\n@@ -82,14 +82,14 @@ HeaderParser.prototype.push = function (data) {\n HeaderParser.prototype.reset = function () {\n this.finished = false\n this.buffer = ''\n- this.header = {}\n+ this.header = Object.create(null)\n this.tail = ''\n }\n \n HeaderParser.prototype._finish = function () {\n if (this.buffer) { this._parseHeader() }\n const header = this.header\n- this.header = {}\n+ this.header = Object.create(null)\n this.buffer = ''\n this.tail = ''\n this.finished = true\n\n\nThis fix is complete and robust because it prevents the lookup from resolving to any prototype method, ensuring that any user-controlled header keys are treated strictly as isolated data attributes.
Exploitation of CVE-2026-19481 requires no authentication or specific configuration. An attacker merely needs to deliver a structured multipart form-data payload containing an HTTP part header named __proto__ or constructor to an endpoint that utilizes the vulnerable library. The parsing engine processes the payload sequentially as it streams from the socket.\n\nThe following sequence diagram illustrates the transaction flow that triggers the crash:\n\nmermaid\ngraph LR\n Attacker[\"Attacker\"] -->|\"1. HTTP POST with __proto__ header\"| WebServer[\"Web Server (Node.js)\"]\n WebServer -->|\"2. Stream request chunks\"| Busboy[\"@fastify/busboy Parser\"]\n Busboy -->|\"3. Extract header name '__proto__'\"| HeaderParser[\"HeaderParser\"]\n HeaderParser -->|\"4. Lookup: this.header['__proto__']\"| Prototype[\"Object.prototype\"]\n HeaderParser -->|\"5. Call: values.push() on Object.prototype\"| Crash[\"TypeError & Process Crash\"]\n\n\nAn attacker can trigger this state using command-line tools such as curl. Because Node.js operates on a single-threaded event loop by default, a synchronous uncaught exception thrown in the main context terminates the entire process immediately. Any active connections are severed, and the service remains unavailable until an external process manager (such as pm2 or systemd) restarts the container or application server.
The Common Vulnerability Scoring System (CVSS) v3.1 rates this vulnerability at a base score of 7.5 (High), reflecting a high availability impact with low complexity and no privileges required. The specific vector is CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. The primary consequence of this vulnerability is systemic Denial of Service (DoS).\n\nBecause @fastify/busboy is often integrated as a low-level parsing utility inside core middleware stacks, a single malicious payload can affect all active users sharing the target process instance. Under rapid attack execution, an attacker can continuously crash newly spawned processes, completely exhausting system resources and causing persistent downtime.\n\nWhile there is no confidentiality or integrity impact (since the vulnerability does not leak memory or permit arbitrary file system access), the disruption to service availability is severe. The EPSS score is 0.00493, representing a low-to-moderate short-term threat, but the trivial nature of the exploit means that public disclosure introduces immediate exploitation risks for unpatched legacy installations.
The primary and recommended resolution is to upgrade @fastify/busboy to version 3.2.1 or later. This release enforces prototype-less object dictionaries throughout the lifecycle of the parser. Organizations using yarn, npm, or pnpm should audit their dependency trees to ensure transitive installations of @fastify/busboy are updated.\n\nIf upgrading immediately is not feasible, temporary mitigation can be applied at the edge of the network. Web Application Firewalls (WAFs) or reverse proxies (such as NGINX or Cloudflare) can be configured to inspect incoming multipart/form-data request bodies. Any request containing header keys such as __proto__: or constructor: within the boundary sections should be rejected with an HTTP 400 Bad Request error.\n\nAdditionally, developers should avoid copying or merging parsed header objects into standard plain objects downstream. Cloning the parsed header collection using spread operators (e.g., { ...headers }) or Object.assign({}, headers) will re-attach the global Object.prototype, potentially introducing secondary prototype lookup or pollution risks within subsequent application logic.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
@fastify/busboy Fastify | >= 1.0.0, <= 3.2.0 | 3.2.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-754 (Variant of CWE-1321 Prototype Pollution via Prototype Lookup Crash) |
| Attack Vector | Network (AV:N) |
| Attack Complexity | Low (AC:L) |
| Privileges Required | None (PR:N) |
| User Interaction | None (UI:N) |
| CVSS v3.1 Score | 7.5 (High) |
| Exploit Status | Proof-of-Concept (PoC) in Test Suite |
| CISA KEV Status | Not Listed |
The software does not check or incorrectly checks for unusual or exceptional conditions, leading to unexpected behavior or resource exhaustion.
SiYuan is an open-source personal knowledge management system. Its Model Context Protocol (MCP) implementation within the asset.upload tool contains a path-traversal and workspace boundary bypass flaw. This allows remote AI models—acting on behalf of attackers via malicious prompts or documents—to import and read sensitive host-system files, such as private keys and system configurations, through absolute path inputs.
An Server-Side Request Forgery (SSRF) vulnerability via DNS-Rebinding Time-of-Check to Time-of-Use (TOCTOU) has been discovered in SiYuan (思源笔记), an open-source personal knowledge management system. The flaw exists within the AI Agent tools http_request (util.HTTPRequest) and web_fetch (util.WebFetch) of the SiYuan Kernel, allowing unauthenticated remote attackers to bypass SSRF validation and access private internal services or cloud metadata endpoints.
An uncontrolled resource consumption vulnerability (CWE-1333 / CWE-400) exists in probe-image-size versions prior to 7.4.0. The SVG parser utilizes an unanchored, inefficient regular expression to find the SVG root tag, leading to catastrophic backtracking when handling malformed payloads. This blocks the single-threaded Node.js event loop, resulting in a complete denial of service.
CVE-2026-10032 is a DOM-based Cross-Site Scripting (XSS) vulnerability in Google's @a2ui/web_core Node.js library. The vulnerability is located within the openUrl utility function, which processes and opens dynamic URLs defined in layout configurations. Because the function fails to sanitize or validate the target URL scheme before passing it to the window.open browser sink, an attacker can specify a javascript: pseudo-protocol to execute arbitrary client-side script in the context of the host origin.
CVE-2026-59944 is a path traversal and link-following vulnerability in Composer, the PHP dependency manager. This flaw allows malicious or compromised packages to bypass previous path-hardening protections and perform arbitrary filesystem operations outside of their designated installation directory, leading to unauthorized permission modifications or execution proxy creations.
A critical Broken Object Level Authorization (BOLA) vulnerability was identified in Trigger.dev before version v4.5.2. An authenticated attacker could trigger a run replay and supply an arbitrary target environmentId belonging to a completely different tenant. Because the server failed to validate whether the target environment belonged to the same project or organization as the source run, it would execute the task within the victim's environment, resulting in unauthorized cross-tenant write operations and remote task execution.