Like a VIP badge scanner that still reads fake laminates if you sneak past the rope line
Fastify versions prior to 5.8.3 contain a flaw in how request.protocol and request.host getters process X-Forwarded-Proto and X-Forwarded-Host headers. When trustProxy is configured with a *restrictive* trust function (a specific IP, subnet, hop count, or custom function), these getters still read forwarded headers from any connection — including untrusted ones that bypass the reverse proxy entirely. An attacker who can open a direct TCP connection to the Fastify listening port can spoof the perceived protocol (e.g., force https on a plaintext connection) and host, potentially undermining HTTPS enforcement, secure cookie flags, CSRF origin checks, and host-based routing. Affected versions: fastify < 5.8.3; fixed in 5.8.3+.
The vendor rates this MEDIUM at CVSS 6.1, and that assessment is *fair to generous*. The AV:A (Adjacent Network) attack vector already encodes the hard prerequisite: the attacker must bypass the reverse proxy and reach the raw Fastify port, which in any competent deployment sits behind an ALB, nginx, or similar edge. The AC:H (High Complexity) further reflects the need for a specific trustProxy configuration. The impact is Confidentiality-High with Scope Changed, but there is no Integrity or Availability impact — the attacker can *read* things they shouldn't by tricking protocol/host logic, but cannot write data or crash the service. With an EPSS of 0.12% (3rd percentile) and zero known exploitation, the real-world risk is narrow.
4 steps from start to impact.
Identify exposed Fastify port
127.0.0.1 or firewalled behind a load balancer, but misconfigured cloud security groups or flat internal networks can leave it reachable. The attacker needs adjacent network access — either on the same VLAN, VPC, or having compromised a neighboring host.- Adjacent network access to the Fastify listening port
- Fastify port not bound to loopback or firewalled
- Most production deployments bind Fastify behind a reverse proxy with the app port unreachable externally
- Cloud deployments typically use security groups/NACLs restricting direct port access
- Container orchestration (ECS, K8s) usually exposes only the load balancer endpoint
Confirm trustProxy restrictive config
trustProxy is set to a restrictive function (IP, subnet, hop count, or custom function) — not when set to true (trust all) or false (trust none). The attacker can infer this by sending a crafted X-Forwarded-Proto: https header on an HTTP connection and observing whether the application behaves as if the connection is HTTPS (e.g., sets Secure cookies, redirects differently). This is a necessary precondition that limits the vulnerable population.- trustProxy configured with restrictive trust function (not
trueorfalse) - Application uses request.protocol or request.host for security logic
- Many Fastify deployments use
trustProxy: true(not vulnerable) ortrustProxy: false(not vulnerable) - Applications that don't rely on request.protocol/request.host for security decisions are unaffected even if the getter is spoofable
Craft spoofed X-Forwarded headers
X-Forwarded-Proto: https and/or X-Forwarded-Host: attacker-controlled.com. Because the vulnerable code reads these headers before checking whether the connection comes from a trusted proxy, the application sees the spoofed values. No special tooling is needed — curl suffices: curl -H 'X-Forwarded-Proto: https' -H 'X-Forwarded-Host: evil.com' http://target:3000/.- Steps 1 and 2 satisfied
- Requires direct TCP to the app port — WAFs and edge proxies in the normal request path strip or override these headers
Exploit spoofed protocol/host
request.protocol and request.host. In the worst case, authentication tokens leak over plaintext; in the common case, the impact is limited to incorrect redirect URLs.- Application makes security-sensitive decisions based on request.protocol or request.host
- Many modern apps use framework-level CSRF protections that don't solely rely on host header matching
- HSTS preload on the domain prevents browser-side protocol downgrade even if the server is confused
- Token leakage requires the attacker to also intercept the plaintext traffic (additional MitM requirement)
request.protocol value.The supporting signals.
| In-the-Wild Exploitation | None observed. Not listed on CISA KEV. No reports of active campaigns or exploitation in the wild as of 2026-08-19. |
|---|---|
| Proof-of-Concept | Trivial to reproduce with curl — the GHSA-444r-cwp2-x5xf advisory describes the exact header manipulation. No weaponized exploit tools circulating. |
| EPSS Score | 0.12% probability of exploitation in next 30 days (3rd percentile). Extremely low predicted exploitation activity. |
| KEV Status | Not listed. No CISA KEV entry. |
| CVSS Vector | CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N — Adjacent network, high complexity, no privileges, scope changed, confidentiality-high only. The AV:A is the key limiter. |
| Affected Versions | fastify < 5.8.3 (all 5.x releases through 5.8.2 when using restrictive trustProxy). Versions using trustProxy: true or trustProxy: false are not affected. |
| Fixed Version | fastify 5.8.3 (npm). No backports to 4.x branch. |
| Exposure / Scanning Data | Fastify receives ~8.5M npm downloads/week with ~5,500 dependent packages. However, direct internet exposure of raw Fastify ports (bypassing reverse proxy) is uncommon — no significant Shodan/Censys fingerprint for exposed Fastify instances. |
| Disclosure Date | 2026-03-24 (published via GitHub Security Advisory and Snyk). |
| Reporting Researcher | Disclosed via the Fastify project's responsible disclosure process. Specific researcher not publicly credited in the advisory. |
noisgate verdict.
The single most decisive factor is the AV:A (adjacent network) prerequisite: exploitation requires direct TCP connectivity to the Fastify application port, bypassing the reverse proxy — a condition absent in the vast majority of production deployments where the app port is firewalled or loopback-bound. Combined with the narrow trustProxy configuration requirement and confidentiality-only impact (no RCE, no integrity, no availability), the real-world risk sits below the vendor's 6.1.
Why this verdict
- Adjacent-network gate: AV:A means the attacker must already have internal network access or be on the same VLAN/VPC. In cloud-native Fastify deployments behind ALBs, security groups block direct port access. This eliminates unauthenticated remote attack from the internet.
- Configuration-dependent: Only fires with restrictive
trustProxysettings (hop count, IP, subnet, custom function). Deployments usingtrustProxy: true(common for apps behind a single trusted proxy) andtrustProxy: falseare unaffected, narrowing the vulnerable population. - Confidentiality-only, no RCE: Impact is limited to protocol/host spoofing leading to potential cookie leakage or CSRF bypass — not remote code execution, not data destruction, not lateral movement.
- Role multiplier: Fastify is an application-tier web framework. It is not a domain controller, hypervisor, identity provider, PAM, backup system, or kernel-mode agent. Its canonical deployment role is a line-of-business API server. Blast radius of a successful exploit is confined to the single application's session/cookie security — host-level at worst, not fleet or domain scale. Even in an API gateway role (via @fastify/http-proxy), the spoofing affects protocol/host perception, not arbitrary command execution. No high-value role floor override applies.
- EPSS 0.12% (3rd percentile): Predictive models rate exploitation probability as extremely low, consistent with zero observed in-the-wild activity.
Why not higher?
Upgrading to HIGH would require either active exploitation, a broader attack vector (AV:N), or a blast radius reaching fleet/domain compromise. None of these conditions are present. The vulnerability cannot achieve RCE, and the adjacent-network prerequisite plus configuration dependency compound to significantly reduce the reachable population. The Scope:Changed flag reflects cross-component impact on downstream security logic, but the actual damage ceiling (cookie/protocol confusion) does not rise to HIGH-tier consequences.
Why not lower?
The Scope:Changed with C:H means a successful exploit can leak authentication tokens or bypass HTTPS enforcement in downstream components beyond the Fastify process itself. While conditions are narrow, the *potential* for credential theft via plaintext cookie leakage is non-trivial in environments where the preconditions are met. Dismissing to LOW would undercount the risk for the subset of deployments with flat networks and restrictive trustProxy configs.
What to do — in priority order.
- Bind Fastify to loopback or restrict with firewall rules — Ensure the Fastify application port (e.g., 3000) is only reachable from the reverse proxy's IP. Use
host: '127.0.0.1'in the Fastify listen config, or enforce security group / iptables rules. This eliminates the AV:A prerequisite entirely. As a MEDIUM verdict, no mitigation SLA applies — go straight to the 365-day remediation window. - Strip X-Forwarded-* headers at the reverse proxy — Configure nginx, HAProxy, or your ALB to overwrite (not append)
X-Forwarded-Proto,X-Forwarded-Host, andX-Forwarded-Forheaders. This ensures only proxy-set values reach Fastify, neutralizing the spoofing vector regardless of Fastify version. - Upgrade to fastify 5.8.3+ — The definitive fix. The patched version correctly gates X-Forwarded-* header processing on whether the connection originates from a trusted proxy IP. Run
npm auditor checkpackage-lock.jsonto verify your installed version across all services. - Audit trustProxy configurations — Grep your codebase for
trustProxysettings. If you're usingtrustProxy: trueortrustProxy: false, you are not affected — document this and close the finding. If using hop count, IP, or custom function, prioritize those services for the upgrade.
- WAF rules on the edge proxy — the vulnerability requires *bypassing* the proxy entirely, so WAF rules on the proxy path don't help if the attacker reaches the app port directly. The WAF never sees the malicious request.
- HSTS headers alone — HSTS protects the browser from protocol downgrade, but server-side logic using
request.protocolis still spoofable. If the app makes backend decisions based on the spoofed protocol (e.g., constructing callback URLs), HSTS doesn't prevent that.
Crowdsourced verification payload.
Run this on each host running a Fastify application, or in your CI pipeline against package.json / package-lock.json. No special privileges needed. Example: bash check_fastify_cve.sh /path/to/your/app
#!/usr/bin/env bash
# Check for CVE-2026-16732 / CVE-2026-3635: Fastify X-Forwarded-* spoofing
# Usage: bash check_fastify_cve.sh /path/to/node/app
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -euo pipefail
APP_DIR="${1:-.}"
FIXED_VERSION="5.8.3"
if [ ! -d "$APP_DIR" ]; then
echo "UNKNOWN - Directory $APP_DIR does not exist"
exit 2
fi
# Try package-lock.json first
LOCK="$APP_DIR/package-lock.json"
if [ -f "$LOCK" ]; then
INSTALLED=$(python3 -c "
import json, sys
with open('$LOCK') as f:
data = json.load(f)
# npm v2+ lockfile format
for key in ['packages', 'dependencies']:
if key in data:
for pkg, info in data[key].items():
if 'fastify' in pkg and 'node_modules/fastify' in pkg or pkg == 'fastify':
v = info.get('version', '')
if v:
print(v)
sys.exit(0)
print('')
" 2>/dev/null)
else
# Fallback: check node_modules
PKG_JSON="$APP_DIR/node_modules/fastify/package.json"
if [ -f "$PKG_JSON" ]; then
INSTALLED=$(python3 -c "import json; print(json.load(open('$PKG_JSON'))['version'])" 2>/dev/null)
else
echo "UNKNOWN - Cannot find fastify in $APP_DIR"
exit 2
fi
fi
if [ -z "$INSTALLED" ]; then
echo "UNKNOWN - Could not determine fastify version"
exit 2
fi
# Compare versions
RESULT=$(python3 -c "
from packaging.version import Version
installed = Version('$INSTALLED')
fixed = Version('$FIXED_VERSION')
if installed >= fixed:
print('PATCHED')
else:
print('VULNERABLE')
" 2>/dev/null || echo "UNKNOWN")
echo "$RESULT - fastify $INSTALLED installed (fixed in >= $FIXED_VERSION)"
case "$RESULT" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esacIf you remember one thing.
npm update fastify with no breaking changes, so there is no reason to wait. Monday morning: run npm audit across your Node.js fleet to identify services still on fastify < 5.8.3. For any hits, verify that the Fastify port is not directly reachable from untrusted network segments (it almost certainly isn't if you're behind an ALB or nginx). If you confirm the app port is firewalled to the proxy, the risk is effectively zero even unpatched. Roll the upgrade into your next scheduled dependency update cycle. No emergency patching warranted.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.