← Back to Feed CACHED · 2026-08-15 14:04:57 · CACHE_KEY CVE-2026-18549
CVE-2026-18549 · CWE-400 · Disclosed 2026-08-14

@fastify/multipart vulnerable to Denial of Service via aborted upload after fileSize limit

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

Like a hotel guest who checks in, floods the bathtub, then leaves without turning off the tap

CVE-2026-18549 affects @fastify/multipart versions 5.3.0 through 10.1.0. When an application uses request.saveRequestFiles() with a fileSize limit (the default configuration), an attacker can send an upload that exceeds the limit and then disconnect before sending the closing multipart boundary. This causes the request handler to hang indefinitely — no response is ever sent, the temporary file is never cleaned up, and the event loop slot is consumed. Repeated exploitation fills os.tmpdir() with orphaned temp files and exhausts Node.js worker capacity, producing a full denial of service. The fix is in version 10.1.1.

The vendor rates this HIGH / 7.5 with a standard unauthenticated-remote-DoS CVSS vector. That rating is *mostly fair* — the attack requires zero authentication, zero user interaction, and is dirt-cheap to execute (a single malformed multipart request plus a TCP reset). However, this is purely an availability impact with no path to code execution, data exfiltration, or lateral movement. The blast radius is the individual Fastify service process, which in most containerized deployments is recoverable via orchestrator restart. A trivial one-line workaround (throwFileSizeLimit: false) exists. These factors push the real-world severity slightly below the vendor label.

"Unauthenticated remote DoS via aborted upload; trivial workaround available, but disk exhaustion can cascade."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify file-upload endpoint

The attacker locates any HTTP endpoint on the target Fastify service that accepts multipart file uploads. This requires no authentication — the endpoint simply needs to invoke request.saveRequestFiles(). Discovery can be done via normal HTTP probing or API documentation.
Conditions required:
  • Target runs @fastify/multipart ≥5.3.0 and <10.1.1
  • Target has at least one endpoint using saveRequestFiles()
Where this breaks in practice:
  • Not all Fastify apps accept file uploads
  • Internal-only APIs behind an API gateway or WAF may not be reachable
Detection/coverage: WAF logs showing repeated multipart POST requests to upload endpoints
STEP 02

Send oversized multipart payload

The attacker sends a multipart POST request with a file part whose body exceeds the configured fileSize limit. The @fastify/busboy parser triggers the file-size-exceeded path, but the request handler awaits a promise that depends on the closing boundary.
Conditions required:
  • fileSize limit is configured (default: 1MB)
  • throwFileSizeLimit is not explicitly set to false
Where this breaks in practice:
  • If the app sets throwFileSizeLimit: false, this path is not reachable
  • Rate-limiting or request-size enforcement at the reverse proxy layer can block oversized uploads
Detection/coverage: Application-level logging of file size limit exceeded events
STEP 03

Abort connection before boundary

The attacker disconnects (TCP RST or simply closes the socket) before sending the closing multipart boundary --boundary--. The busboy parser never emits the finish event, so saveRequestFiles() never resolves. The temp file is written to disk but never cleaned up. The request handler hangs, consuming an event-loop slot and a file descriptor.
Conditions required:
  • Attacker controls when the TCP connection is closed
Where this breaks in practice:
  • Load balancers with request timeouts will eventually reclaim the connection, but the temp file remains on disk
  • Container orchestrators may restart the pod, but accumulated temp files persist on the volume
Detection/coverage: Monitoring for growing temp directory size in os.tmpdir(); Node.js process health checks detecting hung workers
STEP 04

Repeat to exhaust resources

By repeating steps 2-3 across multiple connections, the attacker fills the disk partition hosting os.tmpdir() and/or exhausts all available Node.js worker threads. Once disk is full, the target service (and potentially co-located services) fail. This is a classic asymmetric DoS — each attacker request costs kilobytes of bandwidth but consumes megabytes of disk.
Conditions required:
  • No rate limiting on the upload endpoint
  • Sufficient request volume to fill disk or exhaust workers before timeouts reclaim resources
Where this breaks in practice:
  • CDN/WAF rate limiting can throttle the attack
  • Dedicated tmpdir volumes with quota limits contain the blast radius
  • Kubernetes liveness probes restart hung pods, slowing disk accumulation
Detection/coverage: Disk space alerts on tmpdir partition; container OOMKill or eviction events; APM showing request latency spikes
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo known active exploitation as of 2026-08-15. Not listed on CISA KEV. Disclosed only one day ago (Aug 14, 2026).
Proof of ConceptNo public PoC repository identified, but exploitation is trivially reproducible — a curl command sending a multipart body and then killing the connection suffices. No specialized tooling needed.
EPSS ScoreNot yet scored by FIRST EPSS (CVE too new, published Aug 14 2026). Expect low-to-moderate EPSS given DoS-only impact.
KEV StatusNot listed. DoS-only vulnerabilities rarely make KEV.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — Network-accessible, no auth, no interaction, availability-only impact. Standard unauthenticated DoS vector.
Affected Versions@fastify/multipart ≥ 5.3.0, < 10.1.1 (npm). The legacy fastify-multipart package (deprecated) is also affected if still in use.
Fixed Version10.1.1 (npm). No distro backports expected — this is a Node.js npm package.
Exposure / Install Base~290,000 weekly npm downloads; 429 dependent packages. Widely used in Fastify-based Node.js services. Not externally scannable — requires knowledge of specific endpoints.
Disclosure Date2026-08-14 via GitHub Security Advisory GHSA-vmph-573x-85f6.
Reporteriaohkut-from-NightWolf-Team; fix by UlisesGascon, reviewed by mcollina.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (6.5/10)

Slight downgrade from vendor 7.5 to 6.5 driven by the single decisive factor: DoS-only impact with a trivial one-line configuration workaround (throwFileSizeLimit: false) that fully neutralizes the attack path without requiring a code deploy. The blast radius is limited to the individual Fastify service process — no path to code execution, data breach, or lateral movement exists.

HIGH Vulnerability mechanics and affected versions
HIGH Workaround effectiveness
MEDIUM Real-world exposure (depends on deployment patterns)
LOW EPSS and in-the-wild exploitation (CVE is <48 hours old)

Why this verdict

  • Unauthenticated remote attack with zero complexity — the CVSS base score of 7.5 is technically accurate; any internet-facing Fastify upload endpoint is reachable without credentials.
  • DoS-only, no escalation path — impact is purely availability. No memory corruption, no code execution, no data access. This caps the real-world severity below what an RCE at the same CVSS score would warrant.
  • Trivial config workaround available — setting throwFileSizeLimit: false completely eliminates the vulnerable code path. This is a one-line change deployable via config management in minutes, dramatically reducing the urgency window.
  • Role multiplier: low@fastify/multipart runs inside Node.js application servers. In the typical role (API microservice behind a load balancer), a DoS kills one service instance that Kubernetes or a process manager restarts. In a high-value role scenario (e.g., a Fastify-based API gateway or file-ingestion service), the blast radius is still service-level, not fleet-level or identity-level. The affected component is not a hypervisor, IdP, domain controller, backup server, or security agent — it is an application-layer library. No high-value-role floor applies.
  • Disk exhaustion can cascade — the one factor preventing further downgrade: orphaned temp files accumulate on the host filesystem. If os.tmpdir() shares a partition with other services or the OS root, disk exhaustion can impact co-located workloads, amplifying the blast radius beyond just the Fastify process.

Why not higher?

This cannot be CRITICAL because the impact is strictly availability — there is no code execution, no privilege escalation, no data exfiltration, and no lateral movement path. The affected component is an application-level npm library, not infrastructure software occupying a high-value role. A one-line config workaround fully mitigates the issue.

Why not lower?

This cannot be MEDIUM because the attack is unauthenticated, requires no user interaction, has trivially low complexity, and the disk exhaustion vector can cascade to co-located services. The ~290K weekly downloads indicate wide deployment, and the default configuration (fileSize limit enabled, throwFileSizeLimit not explicitly disabled) means most installations are vulnerable out of the box.

05 · Compensating Control

What to do — in priority order.

  1. Set throwFileSizeLimit: false in multipart plugin options — This is the vendor-recommended workaround. It bypasses the vulnerable code path entirely by not throwing on file size limit, preventing the hang. Deploy this config change within the noisgate mitigation SLA of 30 days for HIGH severity, though given the simplicity, aim for same-week.
  2. Set request timeouts at the reverse proxy layer — Configure nginx/HAProxy/ALB idle timeouts (e.g., 60s) to kill hung connections. This limits worker exhaustion but does NOT prevent temp file accumulation. Deploy as a defense-in-depth layer.
  3. Mount os.tmpdir() on a dedicated volume with quota — Isolate temp file storage so that exhaustion cannot cascade to the root filesystem or other services. Use tmpfs with size limits in containers, or a dedicated EBS/PV with capacity alerts.
  4. Rate-limit multipart POST endpoints — Apply per-IP rate limiting (e.g., 10 req/min) on upload endpoints via WAF or API gateway. This slows disk exhaustion significantly.
  5. Upgrade to @fastify/multipart 10.1.1 — The definitive fix. Plan this upgrade within the noisgate remediation SLA of 180 days for HIGH severity, but prioritize it given the low upgrade friction (minor version bump).
What doesn't work
  • Generic body-size WAF rules — the attack works with payloads that are only slightly above the fileSize limit (e.g., 1.1 MB against a 1 MB limit). Standard WAF max-body rules set to multi-MB thresholds will not catch this.
  • Node.js cluster mode alone — while cluster mode provides multiple workers, each hung request still consumes a worker slot and writes a temp file. The attack simply requires more requests to exhaust all workers.
  • Request body validation middleware — the hang occurs inside saveRequestFiles() before any application-level validation runs. Middleware that validates request content after parsing cannot prevent the issue.
06 · Verification

Crowdsourced verification payload.

Run this on any host or CI runner that has npm or node available. It checks the installed version of @fastify/multipart in the current project directory. No special privileges needed. Example: bash check_cve_2026_18549.sh /path/to/your/node/project

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_18549.sh — Detect CVE-2026-18549 in @fastify/multipart
# Usage: bash check_cve_2026_18549.sh [project_dir]
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

PROJECT_DIR="${1:-.}"
PKG_NAME="@fastify/multipart"
FIXED_VERSION="10.1.1"
MIN_AFFECTED="5.3.0"

if [ ! -d "$PROJECT_DIR/node_modules" ]; then
  echo "UNKNOWN — node_modules not found in $PROJECT_DIR. Run npm install first or specify the correct project directory."
  exit 2
fi

PKG_JSON="$PROJECT_DIR/node_modules/@fastify/multipart/package.json"

if [ ! -f "$PKG_JSON" ]; then
  echo "UNKNOWN — $PKG_NAME is not installed in this project."
  exit 2
fi

INSTALLED=$(node -e "console.log(require('$PKG_JSON').version)" 2>/dev/null)

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

# Compare versions using node's semver-compatible comparison
RESULT=$(node -e "
const v = '$INSTALLED'.split('.').map(Number);
const fix = '$FIXED_VERSION'.split('.').map(Number);
const min = '$MIN_AFFECTED'.split('.').map(Number);
function cmp(a, b) { for (let i = 0; i < 3; i++) { if (a[i] !== b[i]) return a[i] - b[i]; } return 0; }
if (cmp(v, min) < 0) { console.log('NOT_AFFECTED'); }
else if (cmp(v, fix) >= 0) { console.log('PATCHED'); }
else { console.log('VULNERABLE'); }
")

if [ "$RESULT" = "PATCHED" ]; then
  echo "PATCHED — @fastify/multipart $INSTALLED >= $FIXED_VERSION. CVE-2026-18549 is resolved."
  exit 0
elif [ "$RESULT" = "NOT_AFFECTED" ]; then
  echo "PATCHED — @fastify/multipart $INSTALLED is below the affected range ($MIN_AFFECTED). Not vulnerable."
  exit 0
elif [ "$RESULT" = "VULNERABLE" ]; then
  echo "VULNERABLE — @fastify/multipart $INSTALLED is in the affected range ($MIN_AFFECTED to <$FIXED_VERSION). Update to $FIXED_VERSION or set throwFileSizeLimit: false."
  exit 1
else
  echo "UNKNOWN — unexpected comparison result."
  exit 2
fi
07 · Bottom Line

If you remember one thing.

TL;DR
This is a straightforward npm dependency update. Monday morning: run npm ls @fastify/multipart across your Node.js services to identify affected deployments. For any service running versions 5.3.0 through 10.1.0, immediately apply the config workaround (throwFileSizeLimit: false) — this is a zero-risk, one-line change that fully neutralizes the attack. Per the noisgate mitigation SLA for HIGH severity, have this workaround deployed within 30 days, though given its simplicity, same-week is realistic and recommended. Then schedule the actual upgrade to @fastify/[email protected] under the noisgate remediation SLA of 180 days. Also check for the sibling CVE-2026-19474 (temp file leak on aborted upload), which is fixed in the same 10.1.1 release. If any of your Fastify upload services are internet-facing without rate limiting, prioritize those first — the attack is trivial to execute and requires no tooling beyond curl.

Sources

  1. GitHub Security Advisory GHSA-vmph-573x-85f6
  2. GitHub Security Advisory GHSA-62qx-hpj5-j6hc (sibling CVE-2026-19474)
  3. @fastify/multipart npm package
  4. fastify/fastify-multipart GitHub repository
  5. Socket.dev @fastify/multipart security analysis
  6. GitLab Advisory Database — @fastify/multipart
  7. FIRST EPSS API
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.