Like handing a balloon pump a number so big the balloon pops before you even squeeze
CVE-2026-77078 is a denial-of-service flaw in multer, the dominant Express.js middleware for multipart/form-data file uploads (~20 million weekly npm downloads). A single HTTP POST containing two specially crafted text field names triggers an uncaught RangeError: Invalid array length inside the append-field dependency. The first field name uses a massive numeric array index (e.g., field[4294967295]) to allocate a maximum-length sparse array; the second field pushes one element past that ceiling. Because multer never wraps the append-field call in a try/catch, the exception propagates uncaught and terminates the Node.js process. All versions before 2.3.0 are affected — that includes every 1.x release and every 2.x release through 2.2.x.
The vendor's HIGH / 7.5 score is fair and accurate. The CVSS vector (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) correctly reflects that exploitation is unauthenticated, remote, trivially low-complexity, and causes complete availability loss of the affected process. The only mitigating factor the score doesn't capture is that most production Node.js deployments use process managers (PM2, cluster mode, systemd auto-restart) that recover the worker within seconds — so sustained outage requires a loop of requests, not just one. That operational nuance is real but doesn't justify a downgrade: the attacker payload is a single small HTTP request, the package is ubiquitous, and repeated crashes still cause visible service degradation, error spikes, and potential data loss for in-flight uploads.
4 steps from start to impact.
Identify a multer-backed upload endpoint
multer() middleware — typically /upload, /api/files, or any endpoint accepting multipart/form-data. No authentication is required; these endpoints are frequently public-facing for user avatars, document uploads, or form submissions. Scanning tools like httpx or nuclei with content-type probing can enumerate candidates at scale.- Target application uses multer < 2.3.0
- Endpoint accepts multipart/form-data POSTs
- Endpoint may be behind a WAF that limits field name length
- Endpoint may require a valid session/token for the route itself
Send first field with oversized array index
x[4294967295]. When multer passes this to append-field, the library interprets the bracket notation and calls new Array(4294967295), allocating a maximum-length sparse array in the V8 heap. This alone doesn't crash the process — the array is sparse and uses little actual memory — but it sets the trap.- append-field parses bracket notation in field names (default behavior)
- Some custom multer configurations with
fieldNameSizelimits in busboy may truncate the field name before it reaches append-field
Send second field to trigger RangeError
x[push] or simply another x[] entry) causes append-field to call .push() on the already-at-max-length array. V8 throws RangeError: Invalid array length. Because multer's middleware has no try/catch around the append-field invocation, the error becomes an unhandled exception and the Node.js worker process exits immediately.- No external error boundary catching synchronous throws in the middleware chain
- Process managers (PM2, cluster, systemd) restart the worker within 1-5 seconds
- Express global error handlers do NOT catch synchronous throws inside middleware — this is not friction, it's a common misconception
RangeError: Invalid array length with a stack trace through append-field. Node.js uncaughtException handlers that log-and-exit will capture the event.Loop for sustained denial of service
- No rate limiting on the target endpoint
- Process restarts are slower than attacker request rate
- Rate limiting, IP-based throttling, or CDN-level DDoS protection can cap request rate
- Geographic or IP reputation filtering blocks automated sources
- Load balancers with health checks can quarantine crashing instances
The supporting signals.
| In-the-Wild Exploitation | No known exploitation as of 2026-08-29. Disclosed yesterday (2026-08-28). Not listed on CISA KEV. |
|---|---|
| Proof of Concept | No standalone PoC repository identified yet, but the advisory description is a complete recipe — crafting the payload requires only curl and two field names. Expect weaponized PoCs within days. |
| EPSS Score | Not yet scored (CVE published 2026-08-28; EPSS typically populates within 1-3 days of NVD ingestion). |
| KEV Status | Not listed. Pure DoS CVEs rarely make KEV unless tied to ransomware or APT campaigns. |
| CVSS Vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — Network-reachable, zero-click, availability-only impact. No scope change, no C/I impact. |
| Affected Versions | All multer versions < 2.3.0, including the entire 1.x line (1.4.4-lts.1 through 1.4.5-lts.1) and 2.0.0 through 2.2.x. |
| Fixed Version | multer 2.3.0 (released 2026-08-28). The fix adds fieldArrayIndexLimit configuration and wraps append-field calls. |
| Scanning / Exposure | ~20 million weekly npm downloads. Over 6,500 direct dependents on npm. Multer is the de facto file-upload middleware for Express.js — exposure is enormous across SaaS, internal tools, and API backends. |
| Reporter | O4FDev (independent researcher). Fix developed by UlisesGascon (OpenJS Foundation / Express.js maintainer). |
| Related CVEs | Part of a batch of 4 CVEs fixed in multer 2.3.0: CVE-2026-77037, CVE-2026-77063, CVE-2026-82333. Earlier DoS CVEs (CVE-2025-47944, CVE-2025-48997) fixed in 2.0.0 had the same CWE-248 pattern. |
noisgate verdict.
The single most decisive factor is the zero-prerequisite remote attack surface: any unauthenticated HTTP client can crash the target process with a ~200-byte request, and the affected package has 20 million weekly downloads. Impact is capped at availability loss (no RCE, no data breach), which is the single factor preventing escalation to CRITICAL.
Why this verdict
- Unauthenticated remote, zero-click, low-complexity — the CVSS base score correctly captures the trivial attack surface. No friction adjustments are warranted for attacker prerequisites because there are none.
- Massive install base — 20M+ weekly downloads and 6,500+ direct dependents make this one of the most widely deployed npm packages. Even a small fraction of vulnerable deployments represents thousands of targets.
- Process managers provide partial operational mitigation — PM2, cluster mode, and systemd restart workers within seconds, converting a single-shot kill into a degraded-service scenario rather than permanent outage. This is real friction but insufficient to downgrade because the attacker payload is trivially repeatable.
- Role multiplier: Multer is a web-application-tier middleware. In *typical roles* (SaaS backends, internal APIs, admin panels), the blast radius is application-level availability loss — impactful but contained to one service. In *high-value roles* (e.g., an Express-based API gateway fronting microservices, or a CI/CD webhook receiver built on Express), a crash loop could cascade to broader service unavailability. However, even in worst-case high-value deployments, the outcome is availability loss only — no code execution, no credential theft, no lateral movement. The blast radius never reaches domain/fleet/supply-chain compromise, so the floor remains HIGH, not CRITICAL.
Why not higher?
Escalation to CRITICAL would require confidentiality or integrity impact (RCE, data exfiltration) or a blast radius reaching fleet/domain/supply-chain compromise. This is a pure availability bug — it crashes one process at a time, with no path to code execution, privilege escalation, or data access. Process managers limit sustained impact. DoS-only CVEs with no secondary chain are correctly capped at HIGH.
Why not lower?
Downgrading to MEDIUM would require meaningful friction in the attack path — authentication requirements, complex preconditions, or a narrow install base. None exist here: the attack is unauthenticated, single-request, trivially craftable from the advisory text alone, and targets one of the most popular npm packages in existence. The payload will be weaponized in nuclei templates within days of disclosure.
What to do — in priority order.
- Set busboy
fieldNameSizelimit to ≤ 100 bytes — Multer uses busboy under the hood. Configuringlimits: { fieldNameSize: 100 }in your multer options truncates oversized field names before they reachappend-field, neutralizing the array-index trick. Deploy this configuration change within the noisgate mitigation SLA of 30 days (HIGH), though given the trivial exploit, aim for days not weeks. - Add WAF rule blocking numeric array indices > 6 digits in multipart field names — A regex-based WAF rule (e.g., in Cloudflare, AWS WAF, or ModSecurity) matching
\[\d{7,}\]inContent-Dispositionfield names will drop the malicious payload before it reaches your application. This is a defense-in-depth layer while you patch. - Enable rate limiting on upload endpoints — Rate limiting (e.g., 10 requests/second per IP on file-upload routes) prevents an attacker from sustaining a crash loop even if individual requests succeed. Use your reverse proxy (nginx
limit_req, Envoy, Cloudflare Rate Limiting) to enforce this. - Ensure process managers are configured with restart limits and alerting — Verify PM2, systemd, or your container orchestrator (Kubernetes liveness probes) will restart crashed workers quickly but also alert on rapid restart cycles. Set
max_restartswith backoff to avoid infinite crash-restart loops consuming resources.
- Express global error handler (
app.use((err, req, res, next) => ...)) — does NOT catch this crash. The RangeError is a synchronous throw inside middleware, not an error passed tonext(err). Express error handlers only catch errors routed through thenext()callback. process.on('uncaughtException')with continue — while this handler fires, the Node.js docs explicitly warn against continuing after uncaught exceptions because process state is undefined. It can log the crash but should not be used as a mitigation to keep the process alive.- Helmet.js or CORS middleware — these are HTTP header/security middlewares and have zero interaction with multipart field name parsing. They provide no protection against this CVE.
Crowdsourced verification payload.
Run this on any host where your Node.js application is deployed, or in your CI pipeline. Requires node and npm in PATH. No elevated privileges needed. Example: bash check_cve_2026_77078.sh /path/to/your/app
#!/usr/bin/env bash
# check_cve_2026_77078.sh — Detect multer < 2.3.0 (CVE-2026-77078)
# Usage: bash check_cve_2026_77078.sh [/path/to/project]
# Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN
set -euo pipefail
PROJECT_DIR="${1:-.}"
if [ ! -d "$PROJECT_DIR/node_modules" ]; then
echo "UNKNOWN — no node_modules found in $PROJECT_DIR. Run npm install first or provide the correct path."
exit 2
fi
# Check if multer is installed
MULTER_PKG="$PROJECT_DIR/node_modules/multer/package.json"
if [ ! -f "$MULTER_PKG" ]; then
echo "PATCHED — multer is not installed in this project (not affected)."
exit 0
fi
# Extract version
VERSION=$(node -e "console.log(require('$MULTER_PKG').version)" 2>/dev/null)
if [ -z "$VERSION" ]; then
echo "UNKNOWN — could not read multer version from $MULTER_PKG."
exit 2
fi
# Compare version: vulnerable if < 2.3.0
IS_VULN=$(node -e "
const semver = require('semver') || null;
const v = '$VERSION';
// Simple comparison without semver module
const parts = v.split('.').map(Number);
if (parts[0] < 2) { console.log('yes'); }
else if (parts[0] === 2 && parts[1] < 3) { console.log('yes'); }
else { console.log('no'); }
" 2>/dev/null)
if [ "$IS_VULN" = "yes" ]; then
echo "VULNERABLE — multer $VERSION is installed (CVE-2026-77078 affects all versions < 2.3.0). Upgrade to >= 2.3.0."
exit 1
else
echo "PATCHED — multer $VERSION is installed (>= 2.3.0, not affected by CVE-2026-77078)."
exit 0
fiIf you remember one thing.
npm audit across all Node.js repositories to identify multer < 2.3.0 instances, then immediately apply the fieldNameSize busboy limit as a compensating control (noisgate mitigation SLA: within 30 days for HIGH, but given zero-friction exploitability, push this config change out this week). Schedule the actual npm update multer to 2.3.0 across all services within the noisgate remediation SLA of 180 days — but realistically, this is a one-line package.json bump with no breaking API changes, so target completion within 2-3 weeks. Prioritize any public-facing upload endpoints first. If you run multer behind a WAF, deploy the numeric array-index field-name rule today as an additional safety net.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.