← Back to Feed CACHED · 2026-08-29 13:29:09 · CACHE_KEY CVE-2026-77063
CVE-2026-77063 · CWE-362 · Disclosed 2026-08-28

multer is a middleware for handling multipart/form-data in Node.js.

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

It's like picking a lock on a door that's already welded shut from the other side

CVE-2026-77063 is a race condition in multer, the dominant file-upload middleware for Express.js / Node.js, affecting all versions before 2.3.0. When an application configures *both* an asynchronous fileFilter callback *and* a fileSize limit on multer.diskStorage() or multer.memoryStorage(), the async filter's resolution can race against the size-limit enforcement path. If the race is lost by the limiter, the middleware emits a success response for a file that should have been rejected for exceeding limits.fileSize. The practical footprint is narrowed further: only applications combining both async fileFilter and a fileSize limit trigger the race window.

The vendor's LOW / 3.7 score is accurate and honest. The CVSS vector (AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N) correctly captures: network-reachable but high complexity, no auth required, no confidentiality or availability impact, and only low integrity impact. Critically, the advisory itself notes that the underlying busboy / multipart parser still truncates the stream at the configured size limit, so even a 'successful' bypass doesn't deliver a full oversized file to disk or memory — the data is cut off. This makes the real-world impact even lower than the CVSS suggests: the attacker bypasses the *rejection message*, not the actual size enforcement.

"Race condition with a safety net — parser truncation neuters the bypass before it matters."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify a multer-powered upload endpoint

The attacker locates an HTTP endpoint accepting multipart/form-data uploads. Because multer serves ~20 million npm weekly downloads, these are extremely common in Node.js web apps. The attacker confirms the endpoint enforces a file-size limit (e.g., via 413 Payload Too Large or a custom error).
Conditions required:
  • Target runs a Node.js app with multer < 2.3.0
  • Endpoint accepts file uploads
Where this breaks in practice:
  • Many apps use synchronous fileFilter or no fileFilter at all, which is not vulnerable
STEP 02

Confirm async fileFilter + fileSize limit

The race condition only fires when the app registers an *asynchronous* fileFilter callback alongside limits.fileSize. The attacker has no reliable way to fingerprint this server-side configuration remotely — it requires source code review or blind fuzzing with timing analysis. This dramatically reduces practical exploitability.
Conditions required:
  • Application uses async fileFilter callback
  • Application sets limits.fileSize
Where this breaks in practice:
  • No remote fingerprinting method exists for this config combo
  • Many production apps use sync fileFilter or omit it entirely
STEP 03

Race the async filter against the size limiter

The attacker sends a file whose size exceeds limits.fileSize and attempts to win a timing race so the async filter resolves *after* the limiter has started but *before* it can reject the request. The race window depends on event-loop scheduling and the duration of the async filter (e.g., a database lookup). Success is probabilistic, not deterministic.
Conditions required:
  • Async filter takes enough time to open a race window
  • Attacker can send repeated uploads to increase odds
Where this breaks in practice:
  • Race conditions in the Node.js single-threaded event loop have narrow, non-deterministic windows
  • Rate limiting, WAF, or upload throttling reduces retry capacity
Detection/coverage: Standard request-rate monitoring and WAF upload-size rules catch high-volume upload attempts
STEP 04

File accepted — but still truncated

If the race is won, multer accepts the upload without returning a size-limit error. However, the underlying multipart parser (busboy) still truncates the stream at the configured byte limit. The file written to disk or buffer is the same size it would have been anyway — the attacker merely avoided the rejection response. No oversized payload actually lands.
Conditions required:
  • Race condition successfully triggered
Where this breaks in practice:
  • Parser-level truncation is a hard backstop the attacker cannot bypass through this CVE
  • The 'bypass' delivers no additional data to the server
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not listed on CISA KEV. No campaign reports from any threat-intel vendor as of 2026-08-29.
Proof of conceptNone public. No PoC repos found on GitHub or exploit databases. The race condition is non-trivial to reproduce reliably.
EPSSNot yet scored (CVE published 2026-08-28, EPSS typically populates within 24-48 hours). Expected to be very low given LOW severity and no PoC.
KEV statusNot listed. No CISA KEV entry.
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N — Network vector but High complexity. Integrity-only impact at Low level. No confidentiality or availability impact.
Affected versionsmulter < 2.3.0 (all prior versions when using async fileFilter + fileSize limit)
Fixed versionmulter 2.3.0 (GitHub advisory GHSA-qvfw-j98x-7q72)
Install base~20 million weekly npm downloads. Key ecosystem package for Node.js file uploads. However, only the subset using async fileFilter + fileSize limits is affected.
Disclosure date2026-08-28 (reserved 2026-08-20). Published via OpenJS Foundation CNA.
ReporterThinkerHao (reporter); bjohansebas (fix author); UlisesGascon (fix reviewer)
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to LOW (3.7/10)

The single most decisive factor is the parser-level truncation backstop: even when the race condition succeeds, the underlying busboy parser still enforces the byte limit, so no oversized data actually reaches the application — the attacker bypasses only the rejection message, not the size enforcement itself. This reduces the real-world integrity impact to near-zero, fully justifying the vendor's LOW rating.

HIGH Vendor severity assessment accuracy
HIGH No active exploitation or PoC
MEDIUM Fraction of installs using vulnerable config path (async fileFilter + fileSize)

Why this verdict

  • Parser backstop nullifies impact: Even a successful race only bypasses the rejection *response*, not the actual byte truncation. The file on disk is the same size either way — the attacker gains nothing tangible.
  • High attack complexity with no reliable trigger: The race depends on Node.js event-loop timing and the duration of the async fileFilter callback. It is probabilistic, not weaponizable at scale.
  • Narrow configuration surface: Only apps combining async fileFilter AND fileSize limits are affected. Many multer deployments use synchronous filters or no filter at all, shrinking the vulnerable population well below the 20M-download install base.
  • Role multiplier: multer is an application-layer npm middleware, not infrastructure software. (a) *Low-value role:* dev servers, internal tools — negligible impact. (b) *Typical role:* line-of-business Node.js APIs — impact is a cosmetic bypass of an error message, no data exposure. (c) *High-value role:* a Node.js API fronting regulated data — even here, the parser truncation means no oversized payload lands. The blast radius is host-local, cosmetic only across all roles. No role elevates this to domain, fleet, or supply-chain impact.

Why not higher?

The vulnerability has zero confidentiality and zero availability impact per the CVSS vector. The integrity impact is further neutered by the parser-level truncation backstop — the attacker cannot deliver oversized content. There is no path from this bug to RCE, privilege escalation, or data exfiltration in any deployment role.

Why not lower?

While the practical impact is near-zero, the bug does represent a real logic flaw in a widely-used package where the middleware's own enforcement fails. An application relying solely on multer's rejection callback for business logic (e.g., logging rejected uploads, user-facing error messages) would behave incorrectly. This is a legitimate, if minor, integrity issue — not ignorable.

05 · Compensating Control

What to do — in priority order.

  1. Add application-level file-size validation after upload — Check req.file.size or Buffer.byteLength in your route handler *after* multer processes the upload, and reject files exceeding your policy. This is a defense-in-depth layer that doesn't depend on multer's limit enforcement. No mitigation SLA applies at LOW severity — treat as backlog hygiene.
  2. Switch to synchronous fileFilter if async logic isn't needed — If your fileFilter doesn't perform I/O (no DB lookups, no async checks), rewrite it as a synchronous callback. Synchronous filters are not affected by this race condition.
  3. Upgrade to multer 2.3.0 — The definitive fix. Run npm install [email protected] or update your package-lock.json. Test file-upload endpoints in staging before production rollout.
What doesn't work
  • WAF file-size limits — A WAF enforcing Content-Length or request body size is a useful layer but doesn't address the race condition in multer's internal logic. It may also not catch Transfer-Encoding: chunked uploads where Content-Length is absent.
  • Rate limiting alone — Throttling upload attempts reduces race-condition retry odds but doesn't fix the underlying bug. With a sufficiently slow async filter, even a single request can trigger the race.
06 · Verification

Crowdsourced verification payload.

Run this on any machine with node and npm installed. It checks the installed multer version in the current project directory. No special privileges needed. Example: bash check_multer_cve_2026_77063.sh /path/to/your/node/project

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

set -euo pipefail

PROJECT_DIR="${1:-.}"

if [ ! -d "$PROJECT_DIR/node_modules/multer" ]; then
  echo "UNKNOWN — multer is not installed in $PROJECT_DIR/node_modules"
  exit 2
fi

VERSION=$(node -e "try { console.log(require('$PROJECT_DIR/node_modules/multer/package.json').version) } catch(e) { console.log('error') }")

if [ "$VERSION" = "error" ]; then
  echo "UNKNOWN — could not read multer version from package.json"
  exit 2
fi

# Compare versions: vulnerable if < 2.3.0
VULN=$(node -e "
const semver = '$VERSION'.split('.').map(Number);
const fixed = [2, 3, 0];
for (let i = 0; i < 3; i++) {
  if (semver[i] < fixed[i]) { console.log('yes'); process.exit(0); }
  if (semver[i] > fixed[i]) { console.log('no'); process.exit(0); }
}
console.log('no');
")

if [ "$VULN" = "yes" ]; then
  echo "VULNERABLE — multer $VERSION is affected by CVE-2026-77063 (fixed in 2.3.0)"
  exit 1
else
  echo "PATCHED — multer $VERSION is >= 2.3.0"
  exit 0
fi
07 · Bottom Line

If you remember one thing.

TL;DR
This is a LOW-severity race condition with near-zero practical impact — the parser truncation backstop means even a successful exploit delivers no oversized data. Under the noisgate remediation SLA for LOW, there is no mitigation SLA and no urgent patch deadline; treat this as backlog hygiene. That said, multer 2.3.0 is a one-line npm install — roll it into your next scheduled dependency update cycle. If you run npm audit in CI, this will flag automatically. Prioritize your team's time on higher-severity items; this one can ride the next sprint's dependency bump.

Sources

  1. CVE-2026-77063 — THREATINT
  2. GitHub Advisory GHSA-qvfw-j98x-7q72
  3. multer on npm
  4. multer — Snyk vulnerability database
  5. Express.js June 2026 Security Releases
  6. multer CHANGELOG
  7. NVD — CVE-2026-77063
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.