← Back to Feed CACHED · 2026-08-13 08:53:23 · CACHE_KEY CVE-2026-19481
CVE-2026-19481 · CWE-754 · Disclosed 2026-08-12

@fastify/busboy vulnerable to Denial of Service via prototype-named multipart part header

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

Like a bouncer who faints when someone shows a fake ID labeled '__proto__'

CVE-2026-19481 affects @fastify/busboy versions >= 1.0.0 and < 3.2.1, the streaming multipart form-data parser used across the Node.js ecosystem — most notably as a transitive dependency of undici and, by extension, Node.js's built-in fetch(). The parser stores part-header names in a plain JavaScript object. When a crafted multipart request includes a header named __proto__ or constructor, the lookup resolves to an inherited prototype value (not an array), and the subsequent .push() call throws an unhandled TypeError. An unauthenticated remote attacker can crash any Node.js process that pipes incoming multipart/form-data through Busboy without an error handler.

The vendor's HIGH / 7.5 rating is defensible from a pure CVSS-vector standpoint — unauthenticated, network-reachable, low-complexity, high availability impact. But it overstates the real-world pain. The blast radius is a single Node.js worker process crash, not data loss or code execution. Production deployments behind PM2, systemd, or Kubernetes will auto-restart the process in under a second. Applications using the idiomatic req.pipe(busboy) pattern surface the error as an event rather than a hard crash. The fix (upgrade or add an error listener) is trivial. This is a nuisance DoS, not a service-killer.

"DoS-only crash in multipart parser; auto-restart and error handlers blunt the impact"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify multipart upload endpoint

The attacker locates an HTTP endpoint that accepts multipart/form-data — a file upload route, form submission handler, or API ingestion endpoint. No authentication is required. Endpoints are trivially discoverable via documentation, crawling, or fuzzing Content-Type headers.
Conditions required:
  • Target application uses @fastify/busboy (directly or via @fastify/multipart, undici, or Node built-in fetch with FormData parsing)
  • At least one route accepts multipart/form-data
Where this breaks in practice:
  • Not every Node.js service exposes multipart endpoints — pure JSON APIs are unaffected
  • Reverse proxies or WAFs may reject malformed multipart payloads before they reach the app
STEP 02

Send crafted multipart request with prototype header

The attacker sends a multipart/form-data request containing a part whose header name is __proto__ or constructor. This is a single HTTP request; no tooling beyond curl is required. Example: curl -X POST -F '__proto__=x' https://target/upload. The malformed header name collides with JavaScript's Object prototype chain.
Conditions required:
  • Network reachability to the target endpoint
Where this breaks in practice:
  • Some WAFs (e.g., AWS WAF, Cloudflare) with managed rulesets may flag __proto__ in request bodies as prototype-pollution attempts
  • Rate limiting slows repeated crash attempts
Detection/coverage: WAF rules matching __proto__ or constructor in multipart field names; Snyk, npm audit, and Socket.dev flag the vulnerable @fastify/busboy version
STEP 03

Parser throws unhandled TypeError

Inside Busboy's HeaderParser, the code does this.header[h].push(val). When h is __proto__, this.header[h] resolves to Object.prototype (an object, not an array), and .push() throws TypeError: this.header[h].push is not a function. If the caller does not catch this error, the Node.js process exits.
Conditions required:
  • Application does not attach an error listener to the Busboy stream
  • No global uncaughtException handler
Where this breaks in practice:
  • Idiomatic Fastify multipart integration surfaces this as an error event, not a hard crash
  • Well-written Node.js services have process-level error handlers
  • Process managers (PM2, systemd, Kubernetes) auto-restart crashed workers within ~1 second
Detection/coverage: Application crash logs showing TypeError: this.header[h].push is not a function in busboy's header parser
STEP 04

Temporary denial of service

The Node.js worker process crashes and restarts. In-flight requests on that worker are dropped. The attacker can repeat the request to cause repeated restarts, degrading availability. However, each crash only affects one worker in a clustered deployment, and the service recovers automatically.
Conditions required:
  • Attacker can send requests faster than the process restarts
Where this breaks in practice:
  • Clustered deployments (Node cluster, Kubernetes pods, PM2 cluster mode) limit blast to one worker at a time
  • Rate limiting, IP blocking, or CDN-level DDoS protection can throttle repeat attempts
  • No data exfiltration, no code execution, no persistence — attacker gains nothing beyond transient unavailability
Detection/coverage: Spike in process restart counts; uptime monitoring alerts; HTTP 502/503 error rate increase
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNo known exploitation. Not listed on CISA KEV. No campaigns or threat actor usage reported as of 2026-08-13.
Proof of conceptTrivially reproducible: curl -X POST -F '__proto__=x' http://target/upload. No weaponized tooling needed — the PoC is a one-liner. Reported by researcher kq5y.
EPSSNot yet scored (advisory published 2026-08-12). Expected to be low given DoS-only impact and no weaponized exploitation chain.
KEV statusNot listed. No CISA KEV entry as of 2026-08-13.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — 7.5 HIGH. Network-reachable, no auth, availability-only impact. No confidentiality or integrity impact.
Affected versions@fastify/busboy >= 1.0.0, < 3.2.1. This spans all major releases since the Fastify fork of the original busboy library.
Fixed version@fastify/busboy 3.2.1 (released 2026-08-12)
Exposure population@fastify/busboy has ~13–21 million weekly npm downloads, largely driven by its role as a transitive dependency of undici and Node.js's built-in fetch(). However, only apps that *parse* multipart/form-data via Busboy are vulnerable — pure JSON APIs and non-multipart services are unaffected.
Disclosure date2026-08-12 (coordinated disclosure via GitHub Security Advisory GHSA-x8mw-p69m-v3mx)
Reporterkq5y (reporter); mcollina (Fastify maintainer, remediation); UlisesGascon (review)
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.3/10)

The single most decisive downgrade factor is blast radius limited to transient process crash — the vulnerability yields no code execution, no data access, and no persistence; a crashed Node.js worker auto-restarts in under a second in any production-grade deployment. The availability-only impact against a self-healing runtime makes the vendor's HIGH rating overweight for real-world enterprise risk.

HIGH Vulnerability mechanics and affected version range
HIGH Patch availability and fix completeness
MEDIUM Exposure population estimate (transitive dependency count vs. actually-vulnerable multipart endpoints)

Why this verdict

  • DoS-only, no RCE or data impact. The worst outcome is a process crash — no confidentiality or integrity loss. CVSS correctly scores C:N/I:N, but a 7.5 label implies urgency disproportionate to the real consequence.
  • Auto-restart neutralizes persistence. Production Node.js deployments use PM2, systemd, Kubernetes, or cluster mode. A crashed worker restarts in <1 second. The attacker must sustain a stream of requests to maintain degradation, which is indistinguishable from a volumetric DoS that your existing DDoS defenses already handle.
  • Attack surface is narrower than the download count suggests. @fastify/busboy has ~20M weekly downloads because it's a transitive dep of undici/Node fetch, but the vulnerability only fires when the application *actually parses multipart/form-data through Busboy*. Pure JSON APIs, GraphQL services, and SSR apps are unaffected even if the package is in their node_modules.
  • Trivial workaround available. Adding .on('error', handler) to the Busboy stream or wrapping in try/catch prevents the crash entirely, without upgrading.
  • Role multiplier: @fastify/busboy is an application-layer npm library, not a canonical high-value-role component. (a) *Low-value role* (dev tooling, test harness): crash is irrelevant. (b) *Typical role* (line-of-business API server): crash restarts automatically, impact is seconds of downtime. (c) *High-value role* (CI/CD pipeline accepting artifact uploads, API gateway): even here the blast radius is a single worker process crash with auto-restart — it does not escalate to fleet compromise, identity takeover, or supply-chain pivot. No deployment role produces an outcome that triggers the HIGH floor.

Why not higher?

To warrant HIGH, the vulnerability would need to produce sustained, unrecoverable denial of service or affect a component where even brief downtime causes cascading failure (e.g., a domain controller, hypervisor, or PKI service). This bug crashes one worker process that auto-restarts in under a second. The attacker gains no foothold, no data, and no lateral movement capability. The attack is also fully mitigable by a one-line error handler without even upgrading the package.

Why not lower?

Despite the mitigations, this is still an unauthenticated, network-reachable crash with zero interaction required and trivial exploit complexity — a single curl command. The affected package has massive install-base reach, and not every deployment will have proper error handling or process supervision. For single-process Node.js deployments without restart logic (development servers promoted to production, serverless cold-start scenarios), the crash is real and disruptive. That practical exposure keeps it above LOW.

05 · Compensating Control

What to do — in priority order.

  1. Add error handlers to all Busboy stream instances — Attach .on('error', (err) => { /* log and respond 400 */ }) to every Busboy instance in your codebase. This prevents the TypeError from becoming an uncaught exception. This is a code-level change deployable immediately as a compensating control; no package upgrade required.
  2. Deploy WAF rule blocking __proto__ and constructor in multipart field names — Configure your WAF (AWS WAF, Cloudflare, ModSecurity) to reject multipart/form-data requests containing __proto__, constructor, or __defineGetter__ as field names. This blocks the attack at the network edge before it reaches the application. Deploy within the noisgate remediation window of 365 days, though sooner is better.
  3. Ensure process supervision is configured — Verify that all Node.js services run under PM2, systemd, Kubernetes, or equivalent process manager with automatic restart on crash. This limits the blast radius of any uncaught exception to a sub-second restart.
  4. Upgrade to @fastify/busboy >= 3.2.1 — The definitive fix. Run npm update @fastify/busboy or pin >=3.2.1 in your lockfile. For @fastify/multipart users, update to the latest version that pulls in the patched busboy. This is the remediation action under the noisgate 365-day remediation SLA for MEDIUM.
What doesn't work
  • Rate limiting alone — while it slows repeated crashes, a single request is enough to crash one worker. Rate limiting helps but doesn't prevent the first crash.
  • Input validation on the application route handler — the crash occurs inside Busboy's internal header parser *before* your route handler's validation logic runs, so application-level field-name validation won't intercept it.
  • Upgrading Node.js alone — the vulnerability is in the npm package @fastify/busboy, not in Node.js core. Even though Node.js bundles undici (which depends on @fastify/busboy), the bundled version is only used for fetch() FormData parsing, not for Express/Fastify multipart routes. You must update the npm package independently.
06 · Verification

Crowdsourced verification payload.

Run this on any host where a Node.js application using @fastify/busboy is deployed. Execute as the application user or any user with read access to the project's node_modules. Example: bash check_cve_2026_19481.sh /opt/myapp

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-19481 checker for @fastify/busboy
# Usage: bash check_cve_2026_19481.sh /path/to/node/project
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

PROJECT_DIR="${1:-.}"
PKG_JSON="$PROJECT_DIR/node_modules/@fastify/busboy/package.json"

if [ ! -f "$PKG_JSON" ]; then
  echo "UNKNOWN — @fastify/busboy not found in $PROJECT_DIR/node_modules"
  exit 2
fi

VERSION=$(grep '"version"' "$PKG_JSON" | head -1 | sed 's/.*"version": *"\([^"]*\)".*/\1/')

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

# Compare version against fixed version 3.2.1
# Affected: >= 1.0.0, < 3.2.1
MAJOR=$(echo "$VERSION" | cut -d. -f1)
MINOR=$(echo "$VERSION" | cut -d. -f2)
PATCH=$(echo "$VERSION" | cut -d. -f3 | cut -d- -f1)

if [ "$MAJOR" -lt 1 ]; then
  echo "PATCHED — @fastify/busboy $VERSION is below affected range (< 1.0.0)"
  exit 0
elif [ "$MAJOR" -gt 3 ]; then
  echo "PATCHED — @fastify/busboy $VERSION is above fixed version"
  exit 0
elif [ "$MAJOR" -eq 3 ] && [ "$MINOR" -gt 2 ]; then
  echo "PATCHED — @fastify/busboy $VERSION is above fixed version"
  exit 0
elif [ "$MAJOR" -eq 3 ] && [ "$MINOR" -eq 2 ] && [ "$PATCH" -ge 1 ]; then
  echo "PATCHED — @fastify/busboy $VERSION (>= 3.2.1)"
  exit 0
else
  echo "VULNERABLE — @fastify/busboy $VERSION (CVE-2026-19481, fix in 3.2.1)"
  exit 1
fi
07 · Bottom Line

If you remember one thing.

TL;DR
This is a downgraded MEDIUM (5.3). The vulnerability is real but the blast radius is a transient process crash, not data loss or code execution. There is no noisgate mitigation SLA for MEDIUM — go straight to the 365-day noisgate remediation SLA and schedule the @fastify/busboy upgrade to >= 3.2.1 within your next regular patching cycle. If you run internet-facing multipart upload endpoints on single-process Node.js without process supervision, add .on('error', handler) to your Busboy instances this week as a precaution, but this is not a drop-everything patch. Prioritize your CRITICAL and HIGH queue items first; slot this into your next scheduled dependency update sprint.

Sources

  1. GitHub Security Advisory GHSA-x8mw-p69m-v3mx
  2. @fastify/busboy GitHub Security Overview
  3. @fastify/busboy npm package
  4. Fastify Security Audit 2023-2024
  5. @fastify/busboy Socket.dev Analysis
  6. FIRST EPSS Scoring System
  7. Fastify CVE List — CVEDetails
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.