A bouncer who can't read IPv6 wristbands lets guests sneak into the VIP lounge
CVE-2026-75975 is an improper input validation flaw in fast-uri, a zero-dependency RFC 3986 URI toolbox for Node.js. When normalize() or parse() encounters a malformed bracketed IPv6 literal — e.g. [::not-valid] or [fc00::not-hex] — it silently truncates the trailing garbage instead of erroring, collapsing the address to a different, valid IPv6 like [::] (all-zeroes / unspecified) or [fc00::]. Crucially, parse().error remains unset, so callers checking for errors see none. Affected versions span >= 2.3.1 < 2.4.5, >= 3.0.0 < 3.1.6, and >= 4.0.0 < 4.1.3. Patches landed in 2.4.5, 3.1.6, and 4.1.3 on August 23, 2026.
The vendor rates this HIGH at 7.5 with an unauthenticated-network vector, and that CVSS math is technically correct — *if* you assume the library is the SSRF filter. In practice, fast-uri pulls ~465 million downloads/month almost entirely as a transitive dependency of Fastify's ajv-compiler for JSON Schema $id / $ref resolution, not as a runtime URL gatekeeper. The subset of applications that (a) accept untrusted URLs, (b) pipe them through fast-uri's normalize/parse for host validation, and (c) then make outbound HTTP requests based on the result is narrow. For most Node.js shops, this CVE sits inside your node_modules but never touches a security-relevant code path, making the real-world severity closer to MEDIUM.
4 steps from start to impact.
Identify a target endpoint accepting user-supplied URLs
- Target application exposes a URL-consuming endpoint
- Endpoint is reachable (internet-facing or from an adjacent tenant)
- Many Fastify apps use fast-uri only via ajv for schema validation — they never parse user-supplied URLs through it
- Webhook / URL-preview features are a minority of Node.js service endpoints
Craft a malformed IPv6 URI that truncates to a target address
http://[::ffff:169.254.169.254garbage]/latest/meta-data/ or http://[::1not-hex]/admin. fast-uri's normalize() silently strips the trailing non-hex characters, yielding http://[::ffff:169.254.169.254]/latest/meta-data/ or http://[::1]/admin. No error flag is set.- Application passes the raw URL through fast-uri normalize() or parse() before host validation
- Application does not independently validate IPv6 syntax
- Applications using Node's built-in
new URL()orurl.parse()would reject the malformed input before fast-uri sees it - WAF rules with strict IPv6 bracket validation catch obvious malformed literals
\[[:0-9a-fA-F]*[^\]0-9a-fA-F:] regex in request logsBypass host allowlist / SSRF blocklist
::ffff:169.254.169.254garbage), which doesn't match any blocked pattern. After normalization, the actual outbound request goes to the truncated address — cloud metadata, loopback, or an internal RFC 1918 / ULA endpoint.- SSRF filter logic trusts fast-uri's parsed host rather than re-parsing after normalization
- No secondary validation layer (e.g. dns-rebind protection, egress proxy)
- Defense-in-depth environments use egress proxies or IMDSv2 with hop-limit=1, blocking metadata SSRF regardless
- Cloud metadata endpoints increasingly require tokens (AWS IMDSv2, GCP metadata-flavor header)
Exfiltrate cloud credentials or reach internal services
- Cloud metadata service is accessible and returns credentials (IMDSv1) or internal service is reachable
- Application's IAM role / service account has meaningful permissions
- IMDSv2 enforcement blocks SSRF-based metadata theft on AWS
- GCP requires
Metadata-Flavor: Googleheader which most SSRF vectors don't propagate - Network segmentation / VPC service controls limit lateral movement
The supporting signals.
| In-the-wild exploitation | None observed. Not listed in CISA KEV. No campaign or threat-actor reporting as of 2026-08-24. |
|---|---|
| Proof-of-concept | The GHSA advisory contains inline examples (normalize('http://[::not-valid]/private') → http://[::]/private). No weaponized tooling or standalone exploit repo identified. |
| EPSS | Not yet scored — CVE published 2026-08-23/24; EPSS typically lags 24-48 hours for new entries. |
| KEV status | Not listed as of 2026-08-24. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N — network-reachable, no privileges, no interaction, integrity-only impact. The Scope:Unchanged and C:None are key: the vector models URI forgery, not direct data theft. |
| Affected versions | fast-uri >= 2.3.1 < 2.4.5, >= 3.0.0 < 3.1.6, >= 4.0.0 < 4.1.3 |
| Fixed versions | 2.4.5, 3.1.6, 4.1.3 (released 2026-08-23) |
| Install base / exposure | ~465 million npm downloads/month. Overwhelmingly pulled as a transitive dep of @fastify/ajv-compiler → ajv → fast-uri for JSON Schema resolution. Direct SSRF-filter usage is a small fraction. |
| Disclosure date | 2026-08-23 (GHSA), 2026-08-24 (CVE record) |
| Credited researcher | Reported by Fastify maintainer mcollina (Matteo Collina) via the GitHub Security Advisory process. |
noisgate verdict.
The single most decisive factor is the narrow exploitability window: fast-uri is consumed transitively by ~465M downloads/month for JSON Schema URI resolution, but the SSRF attack path requires the application to explicitly use fast-uri's normalize/parse as its outbound-request URL gatekeeper — a usage pattern that represents a small minority of the installed base. Without that specific code path, the vulnerability is inert.
Why this verdict
- Library-level indirection: The vulnerability is not directly exploitable by sending a packet to a listening service. It requires an application to thread user-controlled URLs through fast-uri's
normalize()orparse()for security decisions, then make outbound requests based on the result — a multi-hop dependency chain. - Transitive dependency dominance: ~99% of fast-uri installs arrive via
@fastify/ajv-compilerfor JSON Schema$id/$refresolution, where the parsed URIs are schema identifiers, not attacker-controlled outbound targets. The SSRF-relevant population is a fraction of a percent of the install base. - Role multiplier: (a) *Low-value role* — dev tooling, CLI scripts using Fastify: SSRF is irrelevant, no outbound request path. (b) *Typical role* — Fastify API server: fast-uri resolves schema URIs at startup, user URLs go through
new URL()ornode:url; chain does not succeed. (c) *High-value role* — webhook processor or URL-preview service using fast-uri as the SSRF filter: chain succeeds, blast radius is host-level (cloud credential theft via metadata). This role exists but is not canonical for fast-uri — it is a general-purpose URI library, not an SSRF-defense product. Estimated share of installs in this role: <1%. Floor does not engage. - No exploitation signal: Zero KEV, zero in-the-wild reports, no weaponized PoC, EPSS not yet scored. The advisory examples are illustrative but not turnkey.
- Compensating controls are common: IMDSv2, egress proxies, and
new URL()re-validation are standard in cloud-native Node.js deployments and independently block the SSRF chain even if fast-uri is vulnerable.
Why not higher?
Upgrading to HIGH would require either active exploitation evidence or a canonical high-value deployment role. fast-uri is a utility parsing library — it is not an identity provider, hypervisor, network edge appliance, or security agent. The SSRF chain requires a specific application-level usage pattern (using fast-uri as the URL validator before outbound requests) that represents a tiny fraction of the 465M monthly downloads. No PoC tooling or campaign activity exists to elevate urgency.
Why not lower?
Downgrading to LOW would undercount the real SSRF risk in the minority of applications that *do* use fast-uri for URL validation. The attack is unauthenticated and requires no user interaction, and the IPv6 truncation trick is simple enough that a motivated attacker could weaponize it quickly. The 465M download footprint means even a small percentage of vulnerable-pattern usage translates to thousands of potentially exploitable services.
What to do — in priority order.
- Enforce IMDSv2 (AWS) or equivalent metadata hardening — Set the instance metadata hop limit to 1 and require token-based access. This kills the highest-value SSRF target (cloud credentials) regardless of the parsing bug. Should already be in place; verify within the 365-day noisgate remediation SLA.
- Re-validate URLs with Node's built-in
new URL()after any fast-uri processing — Node's WHATWG URL parser rejects malformed IPv6 literals that fast-uri silently truncates. Adding anew URL(normalizedUri)check after fast-uri processing catches the discrepancy. Deploy to affected codebases within the remediation window. - Use an egress proxy for all outbound HTTP from application tier — Route server-side requests through a forward proxy (Squid, Envoy, cloud NAT gateway with allowlisting) that independently resolves and validates destination IPs. This provides defense-in-depth against any URL-parsing SSRF variant.
- Upgrade fast-uri to 4.1.3 / 3.1.6 / 2.4.5 — The definitive fix. Run
npm audit fixor pin the patched version. For Fastify apps,npm update @fastify/ajv-compilerwill pull the fixed transitive dependency. Complete within the 365-day noisgate remediation SLA.
- WAF IPv6 blocklists alone — the malformed literal (
[::1garbage]) doesn't match standard IPv6 patterns in most WAF rulesets; the truncation happens *after* the WAF passes the request through. parse().errorchecks — the advisory explicitly notes that malformed IPv6 inputs do NOT set the error flag, so existing error-handling code provides zero protection.- Pinning to an older fast-uri major version — all three release lines (2.x, 3.x, 4.x) back to 2.3.1 are affected; there is no safe old version to retreat to.
Crowdsourced verification payload.
Run this on any host with Node.js and npm/npx available. It checks the installed fast-uri version(s) in the current project's node_modules. No special privileges required. Example: bash check_cve_2026_75975.sh /path/to/your/project
#!/usr/bin/env bash
# check_cve_2026_75975.sh — Detect fast-uri versions vulnerable to CVE-2026-75975
# Usage: bash check_cve_2026_75975.sh [project_dir]
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -euo pipefail
PROJECT_DIR="${1:-.}"
VULN_FOUND=0
if [ ! -d "$PROJECT_DIR/node_modules" ]; then
echo "UNKNOWN — no node_modules found in $PROJECT_DIR"
exit 2
fi
# Find all installed fast-uri instances (may appear multiple times in nested node_modules)
while IFS= read -r pkg_json; do
version=$(node -e "console.log(require('$pkg_json').version)" 2>/dev/null || echo "")
if [ -z "$version" ]; then
continue
fi
# Parse major.minor.patch
IFS='.' read -r major minor patch <<< "$version"
vulnerable=false
# 2.x: >= 2.3.1 and < 2.4.5
if [ "$major" -eq 2 ]; then
if [ "$minor" -gt 4 ] || { [ "$minor" -eq 4 ] && [ "$patch" -ge 5 ]; }; then
vulnerable=false
elif [ "$minor" -gt 3 ] || { [ "$minor" -eq 3 ] && [ "$patch" -ge 1 ]; }; then
vulnerable=true
fi
fi
# 3.x: >= 3.0.0 and < 3.1.6
if [ "$major" -eq 3 ]; then
if [ "$minor" -gt 1 ] || { [ "$minor" -eq 1 ] && [ "$patch" -ge 6 ]; }; then
vulnerable=false
else
vulnerable=true
fi
fi
# 4.x: >= 4.0.0 and < 4.1.3
if [ "$major" -eq 4 ]; then
if [ "$minor" -gt 1 ] || { [ "$minor" -eq 1 ] && [ "$patch" -ge 3 ]; }; then
vulnerable=false
else
vulnerable=true
fi
fi
location=$(dirname "$pkg_json")
if [ "$vulnerable" = true ]; then
echo "VULNERABLE — fast-uri $version at $location"
VULN_FOUND=1
else
echo "PATCHED — fast-uri $version at $location"
fi
done < <(find "$PROJECT_DIR/node_modules" -path '*/fast-uri/package.json' -not -path '*/\.cache/*' 2>/dev/null)
if [ "$VULN_FOUND" -eq 1 ]; then
echo "\nResult: VULNERABLE — update fast-uri to 2.4.5 / 3.1.6 / 4.1.3+"
exit 1
elif [ "$VULN_FOUND" -eq 0 ]; then
# Check if we found any fast-uri at all
count=$(find "$PROJECT_DIR/node_modules" -path '*/fast-uri/package.json' 2>/dev/null | wc -l)
if [ "$count" -eq 0 ]; then
echo "UNKNOWN — fast-uri not found in $PROJECT_DIR/node_modules"
exit 2
fi
echo "\nResult: PATCHED"
exit 0
fiIf you remember one thing.
npm audit across your Node.js estate this week to identify which projects carry a vulnerable fast-uri version, then schedule npm update or version pinning into your next regular dependency refresh cycle. If you operate any service that explicitly uses fast-uri to validate user-supplied URLs before making outbound requests (webhook processors, link previewers, SSRF-filtered fetch proxies), treat those services as HIGH-priority exceptions and patch them within 30 days. For everything else — which is the vast majority of Fastify/ajv consumers — the vulnerable code path is never reached, and standard remediation cadence is fine.Sources
- GHSA-f65p-4m7j-42xc — GitHub Security Advisory
- fast-uri npm package
- GitLab Advisory — CVE-2026-18446 (related backslash vuln, version context)
- Rapid7 — CVE-2026-18446 fast-uri vulnerability details
- SentinelOne — CVE-2026-6322 fast-uri SSRF
- Node.js June 2026 Security Releases
- fast-uri security advisories listing
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.