← Back to Feed CACHED · 2026-10-08 01:42:02 · CACHE_KEY CVE-2026-77078
CVE-2026-77078 · CWE-248 · Disclosed 2026-08-28

Multer Denial of Service via Crafted Multipart Field Names (Array Index Overflow)

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Like a bouncer who drops dead the moment someone hands him a comically oversized ID card

CVE-2026-77078 is a denial-of-service flaw in multer, the dominant multipart/form-data parsing middleware for Express.js and Node.js. A remote, unauthenticated attacker can crash an entire Node.js process with a single HTTP request. The attack sends two crafted text field names in a multipart/form-data body: the first field uses a huge numeric array index (near V8's hard ceiling of 4,294,967,295 elements) to force a maximum-length sparse array allocation inside the append-field dependency, and the second field triggers a .push() past that boundary. This throws a synchronous RangeError: Invalid array length that bypasses multer's error handler and kills the process. All multer versions before 2.3.0 are affected — and multer pulls over 22 million weekly npm downloads, so the blast radius across the Node.js ecosystem is vast.

The vendor's HIGH / 7.5 rating is correctly calibrated. The CVSS vector (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) accurately reflects the zero-auth, zero-interaction, network-reachable crash. The only thing keeping this from CRITICAL is the impact ceiling: availability-only, no confidentiality or integrity exposure. In practice, production Node.js services behind PM2, cluster mode, or Kubernetes will auto-restart within seconds — but a sustained stream of these requests produces a sustained outage, and the PoC is public and trivially weaponizable. The vendor got this one right.

"One malformed upload request crashes your entire Node.js process — patch multer now."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify a multer-powered endpoint

The attacker identifies any Express.js route that uses multer middleware — typically a file-upload or form-submission endpoint accepting multipart/form-data. No authentication is required; any publicly reachable route that triggers multer parsing is sufficient. Discovery is straightforward: send a benign multipart POST and observe the response. Common paths include /upload, /api/submit, or any endpoint documented to accept file attachments.
Conditions required:
  • Target application uses multer < 2.3.0
  • Endpoint is network-reachable
Where this breaks in practice:
  • Endpoint may sit behind an API gateway or CDN that strips or normalizes multipart fields, though this is uncommon
STEP 02

Craft the oversized array-index field

The attacker constructs the first field in the multipart body with a name like field[4294967294] — an index at the V8 array-length ceiling. When multer's append-field dependency processes this, it allocates a sparse array of maximum length. The allocation itself succeeds (sparse arrays are lazy in V8), but the internal length property is set to near 2^32 - 1. This step requires only knowledge of the CVE details, which are public.
Conditions required:
  • Ability to send arbitrary multipart field names (standard HTTP)
Where this breaks in practice:
  • WAFs rarely inspect or limit numeric indices inside multipart field names
Detection/coverage: WAF rules inspecting multipart field names for excessively large numeric indices can flag this, but this is not a default ruleset in any major WAF product.
STEP 03

Send the overflow-triggering second field

The second field in the same request uses bracket syntax like field[] (empty brackets), which triggers append-field to call .push() on the already-at-ceiling-length array. V8 throws a synchronous RangeError: Invalid array length. Because multer does not wrap this code path in a try/catch, the exception propagates uncaught, bypassing Express error middleware and terminating the Node.js process immediately.
Conditions required:
  • Both fields delivered in a single multipart request
Where this breaks in practice:
  • Process managers (PM2, cluster mode, Kubernetes) will restart the worker within seconds, but each crash still drops in-flight requests
Detection/coverage: Application-level crash logs will show an uncaught RangeError: Invalid array length from the append-field module. APM tools (Datadog, New Relic) with crash tracking will surface the stack trace.
STEP 04

Sustain the attack for continuous outage

Because the crash requires only a single lightweight HTTP request (~200 bytes), the attacker can loop the request to keep crashing workers as fast as they restart. Against a single-process deployment this produces a hard outage. Against clustered or orchestrated deployments it causes intermittent failures and request drops as workers cycle. The public PoC from wtfkimi/CVE-2026-77078 automates this. No special tooling beyond curl is needed.
Conditions required:
  • Network path to the endpoint remains open
  • No rate-limiting or request-blocking in place
Where this breaks in practice:
  • IP-based rate limiting at the load balancer or CDN layer can throttle sustained attacks
  • Geographic or IP-reputation filtering can reduce attack surface
Detection/coverage: GreyNoise and similar sensors would detect sustained scanning/exploitation. Load balancer logs will show rapid connect/disconnect cycles correlating with worker crashes.
03 · Compensating Control

1
HIGH 7.5→IGNORE 0.0
SEVERITY REDUCED
Upgrade multer to 2.3.0 immediately — The definitive fix. Version 2.3.0 wraps the appendField call in a try/catch and introduces limits.fieldArrayIndexLimit to reject oversized indices before allocation. Run npm update multer or pin "multer": ">=2.3.0" in package.json. As a HIGH-severity finding, the noisgate mitigation SLA requires action within 30 days, but given the trivial exploitability and public PoC, prioritize this in your next sprint.
2
HIGH 7.5→MEDIUM 5.3
SEVERITY REDUCED
Deploy a WAF rule blocking oversized array indices in multipart field names — Configure your WAF (Cloudflare, AWS WAF, Akamai, ModSecurity) to reject multipart/form-data requests where any field name contains a numeric index exceeding a reasonable threshold (e.g., field[999999] and above). This is a stopgap if you cannot patch immediately. ModSecurity example: SecRule ARGS_NAMES "\[\d{6,}\]" "id:100200,phase:2,deny,status:403,msg:'Oversized array index in field name'". Deploy within the 30-day noisgate mitigation SLA.
3
HIGH 7.5→MEDIUM 5.0
SEVERITY REDUCED
Run Node.js in cluster mode or behind a process manager — Ensure production deployments use PM2 cluster mode, Node.js cluster module, or Kubernetes with liveness probes and rapid restart policies. This doesn't prevent the crash but limits downtime per crash to <2 seconds per worker. Against sustained attacks, this converts a hard outage into intermittent request drops — still degraded, but survivable.
4
HIGH 7.5→MEDIUM 5.3
SEVERITY REDUCED
Rate-limit multipart POST requests at the edge — Configure your load balancer or CDN to rate-limit POST requests to upload endpoints (e.g., 10 req/s per IP). This throttles sustained crash-loop attacks. Combine with IP-reputation filtering to block known-bad sources. This doesn't prevent a single crash but prevents sustained outage.
What doesn't work
  • Helmet.js or Express security headers — these operate on HTTP response headers and do not inspect or modify incoming multipart request bodies. They provide no protection against this attack vector.
  • Express error middleware (app.use((err, req, res, next) => ...)) — the uncaught RangeError in append-field fires synchronously outside Express's error-handling pipeline. The middleware never gets a chance to catch it. This is precisely why the bug is dangerous.
  • Setting multer({ limits: { fields: N } }) field count limits — the crash occurs during field-name parsing *before* the field-count limit is evaluated. The limit won't fire in time to prevent the RangeError.
  • Node.js --max-old-space-size memory limits — the sparse array allocation is lazy and doesn't consume proportional memory. The crash is a RangeError from exceeding V8's array-length invariant, not an OOM condition.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNot observed. Not listed in CISA KEV. No campaigns or threat actor usage reported as of 2026-10-08. No GreyNoise or Shadowserver tags for this CVE.
Proof-of-ConceptPublic PoC available. GitHub repo wtfkimi/CVE-2026-77078 provides a TypeScript-based exploit with English and Russian documentation. Also indexed on Sploitus. No nuclei template found yet. Exploitation is trivial — reproducible with a single curl command.
EPSS0.00488 (0.49%) — approximately 70th percentile. Indicates a below-average probability of exploitation in the next 30 days, though the public PoC and trivial exploitation path may push this higher over time.
CISA KEVNot listed as of 2026-10-08.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — Network-reachable, zero complexity, no privileges, no interaction, availability-only impact. The vector accurately captures the threat: easy to fire, hard to miss, but no data at risk.
Affected VersionsAll multer versions < 2.3.0, including the widely-used 1.4.x LTS line. The root cause is in the append-field dependency's array-index handling. Version 2.2.0 is also affected by a related file-descriptor leak (CVE-2026-77037).
Fixed Versionmulter 2.3.0 (released 2026-08-31). Fix is in commit 87a584e on expressjs/multer — adds try/catch around appendField and introduces opt-in limits.fieldArrayIndexLimit configuration. No distro backports; npm is the canonical distribution channel.
Installed Base / Exposure~22 million weekly npm downloads. 6,700+ dependent packages in the npm registry. Multer is the de facto standard for file uploads in Express.js. Downstream consumers include NestJS (@nestjs/platform-express), OWASP Juice Shop, IBM OpenPages, and thousands of enterprise Node.js APIs.
Disclosure TimelineDisclosed 2026-08-28. Express.js security release blog post 2026-08-31. Reported by O4FDev, fixed by UlisesGascon.
Related CVEsmulter 2.3.0 also fixes CVE-2026-77037 (fd leak on aborted uploads, HIGH), CVE-2026-82333 (event-loop blocking via oversized index, HIGH), and CVE-2026-77063 (file-size limit bypass, LOW). Upgrading to 2.3.0 addresses all four.

Sources.

  1. GitHub Advisory — GHSA-wc9g-mqfw-jrwm
  2. Express.js August 2026 Security Releases
  3. CVE Reports — CVE-2026-77078 Technical Analysis
  4. PoC — wtfkimi/CVE-2026-77078
  5. multer on npm — Download Statistics
  6. OpenCVE — CVE-2026-77078 Details
  7. GitLab Advisory Database — CVE-2026-77078
05 · The Call

Final Verdict
= UNCHANGED to HIGH (7.5/10)

Why this verdict

  • Zero-friction exploitation path: Unauthenticated, no user interaction, low complexity, single HTTP request. The attacker needs nothing more than curl and the target's URL. Every prerequisite in the chain is met by default in any internet-facing Express.js app using multer. No compounding downward pressure from access requirements.
  • Massive installed base amplifies risk: With ~22M weekly npm downloads and 6,700+ dependents, multer is ubiquitous in the Node.js ecosystem. The fraction of Express.js applications parsing multipart data with multer is enormous — this isn't a niche component.
  • Public PoC lowers the bar to zero: The wtfkimi/CVE-2026-77078 repository provides a ready-made exploit. The payload is ~200 bytes. Weaponization requires no reverse engineering.
  • Role multiplier: Multer runs in Node.js web application backends. (a) *Low-value roles* (dev servers, internal tools): DoS is a nuisance. (b) *Typical roles* (production API servers, SaaS backends): DoS causes customer-facing outages and SLA violations. (c) *High-value roles* (API gateways, payment or auth services on Express.js): DoS disrupts critical business functions. However, the blast radius in all cases is availability-only — no path to domain takeover, fleet compromise, data exfiltration, or supply-chain pivot. The outcome caps at 'service outage,' which does not trigger the HIGH/CRITICAL floor rule. The verdict holds at HIGH on exploitability merits alone.
  • DoS-only impact is the ceiling: The CVSS vector is C:N/I:N/A:H. There is no code execution, no data leakage, no privilege escalation. This is a hard cap that prevents CRITICAL regardless of exploitability.

Why not higher?

CRITICAL requires confidentiality or integrity impact, or an availability impact that cascades to domain/fleet/supply-chain compromise. This CVE is strictly availability-only — it crashes a single Node.js process. Even against high-value Express.js services, the blast radius is bounded to service outage, not lateral movement or data breach. Process managers further limit sustained impact.

Why not lower?

Downgrading to MEDIUM would require meaningful friction in the exploitation chain, but there is none: the attack is unauthenticated, remote, low-complexity, and requires a single request against the most popular file-upload middleware in the Node.js ecosystem. The public PoC eliminates any skill barrier. The 22M-download installed base means this affects a significant fraction of all Node.js web applications. The EPSS is modest (0.49%) and KEV is empty, but the raw exploitability against an enormous attack surface justifies HIGH.

06 · Verification

Crowdsourced verification payload.

Run this script on any host where the Node.js application is deployed, or on a CI runner that has access to the project's node_modules. No special privileges required — it reads package.json metadata. Invoke with: bash check_multer_cve_2026_77078.sh /path/to/your/project

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_multer_cve_2026_77078.sh
# Checks whether the installed multer version is vulnerable to CVE-2026-77078
# Usage: bash check_multer_cve_2026_77078.sh /path/to/project
# Exit codes: 1 = VULNERABLE, 0 = PATCHED, 2 = UNKNOWN

set -euo pipefail

PROJECT_DIR="${1:-.}"
PKG_JSON="${PROJECT_DIR}/node_modules/multer/package.json"

if [ ! -f "$PKG_JSON" ]; then
  echo "UNKNOWN — multer not found in ${PROJECT_DIR}/node_modules/"
  echo "Either multer is not installed, or the path is wrong."
  exit 2
fi

# Extract version from package.json
VERSION=$(grep -o '"version": *"[^"]*"' "$PKG_JSON" | head -1 | sed 's/"version": *"//;s/"//')

if [ -z "$VERSION" ]; then
  echo "UNKNOWN — could not parse version from $PKG_JSON"
  exit 2
fi

echo "Detected multer version: $VERSION"

# Compare version against fixed version 2.3.0
# Split version into components
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"

# Strip any pre-release suffix from PATCH for numeric comparison
PATCH_NUM=$(echo "$PATCH" | grep -o '^[0-9]*')

if [ -z "$MAJOR" ] || [ -z "$MINOR" ] || [ -z "$PATCH_NUM" ]; then
  echo "UNKNOWN — could not parse semver components from version $VERSION"
  exit 2
fi

# Fixed in 2.3.0. Vulnerable if < 2.3.0.
if [ "$MAJOR" -lt 2 ]; then
  echo "VULNERABLE — multer $VERSION is affected by CVE-2026-77078 (all versions < 2.3.0)"
  echo "Upgrade to multer >= 2.3.0: npm install multer@latest"
  exit 1
elif [ "$MAJOR" -eq 2 ] && [ "$MINOR" -lt 3 ]; then
  echo "VULNERABLE — multer $VERSION is affected by CVE-2026-77078 (all versions < 2.3.0)"
  echo "Upgrade to multer >= 2.3.0: npm install multer@latest"
  exit 1
elif [ "$MAJOR" -eq 2 ] && [ "$MINOR" -eq 3 ] && [ "$PATCH_NUM" -lt 0 ]; then
  echo "VULNERABLE — multer $VERSION is affected by CVE-2026-77078 (all versions < 2.3.0)"
  echo "Upgrade to multer >= 2.3.0: npm install multer@latest"
  exit 1
else
  echo "PATCHED — multer $VERSION is not affected by CVE-2026-77078"
  exit 0
fi