← Back to Feed CACHED · 2026-09-15 11:03:13 · CACHE_KEY CVE-2026-86472
CVE-2026-86472 · CWE-178 · Disclosed 2026-09-15

fast-uri vulnerable to inconsistent host case normalization via percent-encoded octets

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

It's like a bouncer who checks the guest list before putting on his reading glasses

CVE-2026-86472 affects the fast-uri npm package (versions < 2.4.7, 3.0.0–3.1.7, 4.0.0–4.1.4), a dependency-free RFC 3986 URI toolbox with ~100 million weekly downloads. The bug is a sequencing error: normalize() folds the hostname to lowercase *before* percent-decoding, so %41 (which should decode to a) survives as uppercase A. The result is that parse('//%41.com').host returns A.com while parse('//a.com').host returns a.com. Applications performing case-sensitive host checks against parsed output can reach inconsistent conclusions about the same effective destination.

The vendor's MEDIUM / 4.8 is already modest, but it still overstates the practical risk. The CVSS vector correctly sets AC:H (high attack complexity), yet the real friction is deeper than complexity alone. Over 99% of fast-uri's install base consumes it transitively through AJV and Fastify for JSON Schema $ref resolution — not for security-relevant URL validation. An attacker must find an application that (a) directly uses fast-uri's host output for access-control decisions, (b) performs that comparison case-sensitively, and (c) accepts attacker-controlled URLs. That three-gate chain makes exploitation a niche scenario, not a fleet-wide concern.

"Library-level case-folding ordering bug; real-world exploitability needs a rare usage pattern most apps never hit."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify target application using fast-uri for host validation

The attacker must find a Node.js service that calls fast-uri.parse() or fast-uri.normalize() on untrusted URLs and then checks the parsed .host property against a denylist or allowlist. This is an uncommon pattern — most fast-uri consumers inherit it through AJV for schema validation, not URL policy enforcement.
Conditions required:
  • Target app uses fast-uri directly (not just transitively via AJV)
  • App uses parsed host for security-critical decisions
Where this breaks in practice:
  • Vast majority of fast-uri installs are transitive AJV/Fastify deps
  • Application must expose a URL input surface to attacker
STEP 02

Craft URL with percent-encoded hostname octets

The attacker constructs a URL where hostname characters are percent-encoded, e.g. http://%49nternal.corp.com/secret. Because fast-uri lowercases *before* decoding, the parsed host becomes Internal.corp.com instead of internal.corp.com. No tooling beyond a browser or curl is needed.
Conditions required:
  • Knowledge of the target's denylist/allowlist entries
  • Ability to submit crafted URLs to the application
Where this breaks in practice:
  • DNS is case-insensitive, so the resolved IP is identical regardless of casing
  • Many apps use .toLowerCase() on host before comparison, negating the bug
STEP 03

Bypass case-sensitive host check

If the app performs a strict equality check like parsed.host === 'internal.corp.com', the percent-encoded variant yields Internal.corp.com which does not match. For a denylist, this means the blocked host is reachable; for an allowlist, the legitimate host is rejected (DoS, not escalation). The attacker's interesting path is denylist bypass leading to SSRF.
Conditions required:
  • Host comparison must be case-sensitive (===, not case-folded)
  • Denylist scenario for offensive value
Where this breaks in practice:
  • Downstream HTTP clients (Node fetch, axios) resolve DNS case-insensitively — the actual connection target is unchanged
  • Modern SSRF frameworks typically validate at the IP/socket level, not hostname string level
Detection/coverage: WAFs and SSRF filters operating on raw request URLs (not parsed host) would see the percent-encoded form and may flag it.
STEP 04

Reach internal resource via SSRF

If the denylist bypass succeeds and the downstream HTTP client follows the URL, the attacker reaches the nominally blocked internal endpoint. Impact is bounded by what that endpoint exposes — typically metadata services, internal APIs, or cloud instance credentials.
Conditions required:
  • Vulnerable app proxies or fetches the attacker-supplied URL server-side
  • Internal target has exploitable resources
Where this breaks in practice:
  • Cloud metadata services (169.254.169.254) are IP-based, not hostname-based — this bug doesn't help
  • Most SSRF-hardened apps validate resolved IPs, not just hostnames
Detection/coverage: Cloud provider metadata endpoint access logs; network-level SSRF detection in WAF/CSPM.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. Not listed in CISA KEV. No known campaigns or threat actor usage.
Proof of conceptAdvisory includes a trivial one-liner: parse('//%41.com').hostA.com. No weaponized PoC or exploit tool exists.
EPSS scoreNot yet scored (published 2026-09-15). Expected to land in the bottom quartile given AC:H and library-level impact.
KEV statusNot listed. No federal mandate to patch.
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N — network-reachable but high complexity, low confidentiality and integrity impact, no availability impact.
Affected versionsfast-uri < 2.4.7, 3.0.0–3.1.7, 4.0.0–4.1.4
Fixed versions2.4.7, 3.1.8, 4.1.5
Exposure / install base~100M weekly npm downloads, but 303 direct dependents. Overwhelmingly consumed transitively via AJV and Fastify for schema validation, not URL security.
Disclosure date2026-09-15 (coordinated disclosure via GitHub Security Advisory GHSA-hrr3-gc8f-f4qj)
Reporter / maintainerDisclosed via Fastify project; patch authored by Matteo Collina (@mcollina).
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.0/10)

The single most decisive factor is the vanishingly narrow exploitable usage pattern: over 99% of fast-uri's ~100M weekly installs consume it as a transitive AJV/Fastify dependency for JSON Schema resolution, where hostname casing is security-irrelevant. Exploitation requires a bespoke application that directly uses fast-uri's parsed host for case-sensitive security decisions on attacker-controlled URLs — a three-gate chain that collapses the reachable population to a rounding error of the install base.

HIGH Vulnerability mechanics and affected versions
HIGH Verdict direction (downgrade from MEDIUM)
MEDIUM Fraction of installs using fast-uri for host-based security decisions

Why this verdict

  • Transitive-only exposure for 99%+ of installs: fast-uri's 100M weekly downloads are driven by AJV and Fastify, which use it for $ref resolution in JSON Schema — not for URL allowlist/denylist enforcement. The bug is unreachable in this dominant usage path.
  • Three-gate exploitation chain: Attacker needs (1) an app calling fast-uri.parse() on user input, (2) case-sensitive host comparison for access control, (3) server-side fetch of the resulting URL. Each gate eliminates most of the remaining population.
  • DNS case-insensitivity neutralizes impact: Even when the parsed host string differs in casing, DNS resolution is case-insensitive. The downstream HTTP client connects to the same IP regardless, meaning the bug only matters when the *string comparison* is the security boundary — not the network connection.
  • Role multiplier: fast-uri is a utility library, not a component that defines a deployment role. It appears in CI/CD (build-time via Webpack/schema-utils), in API servers (Fastify), and in validation layers (AJV). In none of these canonical roles does the host-casing bug grant domain takeover, fleet compromise, or supply-chain pivot. The blast radius is limited to the individual application's URL-validation logic — host-level, not fleet-level. No high-value role floor applies.
  • No exploitation evidence, no weaponized tooling: Zero in-the-wild activity, no KEV listing, no researcher PoC beyond the advisory's one-liner example.

Why not higher?

Upgrading to MEDIUM or above would require either active exploitation evidence or a broader blast radius. The bug does not enable RCE, privilege escalation, or data exfiltration on its own — it is a logic inconsistency that *might* weaken a host check in a bespoke application. The vendor's own AC:H rating already acknowledges the difficulty, and the real-world narrowing (transitive-only usage, DNS case-insensitivity) compounds further.

Why not lower?

A full IGNORE verdict would be inappropriate because the bug *is* real and *could* weaken SSRF protections in the small population of apps that directly use fast-uri for URL policy. The advisory example is trivially reproducible, the fix is a one-line npm update, and defenders should still track it for completeness.

05 · Compensating Control

What to do — in priority order.

  1. Lowercase parsed hosts before comparison — Add .toLowerCase() to any code path that compares fast-uri.parse().host against allow/deny lists. This neutralizes the bug entirely and takes minutes to deploy. No deadline pressure — this is a LOW finding, so treat as backlog hygiene.
  2. Validate at the IP/socket layer for SSRF — Instead of comparing hostname strings, resolve the URL to an IP address and validate against blocked CIDR ranges (e.g., 169.254.0.0/16, 10.0.0.0/8, 127.0.0.0/8). This is the correct SSRF defense regardless of this CVE.
  3. Upgrade fast-uri to patched version — Run npm audit fix or pin fast-uri to >=2.4.7 / >=3.1.8 / >=4.1.5. Since this is a LOW verdict, fold into your next scheduled dependency update cycle within 365 days per the noisgate remediation SLA.
What doesn't work
  • WAF URL-decoding rules — Most WAFs decode percent-encoding in paths and query strings but do not normalize hostname casing. The bypass operates at the hostname level before the WAF's purview.
  • Content Security Policy (CSP) — CSP is a browser-side control; this vulnerability is server-side URL parsing. CSP headers have no effect on server-side host validation logic.
06 · Verification

Crowdsourced verification payload.

Run on any machine with Node.js installed. Execute: node /tmp/check-fast-uri-cve-2026-86472.js. No special privileges required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env node
// CVE-2026-86472 - fast-uri inconsistent host case normalization
// Outputs: VULNERABLE / PATCHED / UNKNOWN

try {
  const fastUri = require('fast-uri');
  const pkg = require('fast-uri/package.json');
  const version = pkg.version;

  // Test: parse a URL with percent-encoded uppercase octet in host
  const result = fastUri.parse('//%41.example.com');
  const host = result.host || '';

  // In patched versions, host should be lowercased to 'a.example.com'
  // In vulnerable versions, host will be 'A.example.com'
  if (host === 'A.example.com' || host === '%41.example.com') {
    console.log('VULNERABLE');
    console.log('fast-uri version: ' + version);
    console.log('Parsed host: ' + host + ' (expected: a.example.com)');
    process.exit(1);
  } else if (host.toLowerCase() === 'a.example.com') {
    console.log('PATCHED');
    console.log('fast-uri version: ' + version);
    console.log('Parsed host: ' + host);
    process.exit(0);
  } else {
    console.log('UNKNOWN');
    console.log('fast-uri version: ' + version);
    console.log('Unexpected host value: ' + host);
    process.exit(2);
  }
} catch (e) {
  if (e.code === 'MODULE_NOT_FOUND') {
    console.log('UNKNOWN');
    console.log('fast-uri is not installed in this project.');
    process.exit(2);
  }
  console.log('UNKNOWN');
  console.log('Error: ' + e.message);
  process.exit(2);
}
07 · Bottom Line

If you remember one thing.

TL;DR
This is a LOW finding. There is no noisgate mitigation SLA for LOW-severity issues — treat it as backlog hygiene. When you next run your scheduled dependency update cycle, bump fast-uri to >=2.4.7 (v2.x), >=3.1.8 (v3.x), or >=4.1.5 (v4.x). If you have a Node.js service that directly calls fast-uri.parse() on user-supplied URLs and checks the host for access control, add .toLowerCase() to that comparison as an immediate one-line fix. For the 99%+ of your estate where fast-uri is a transitive AJV/Fastify dependency used for JSON Schema resolution, this CVE is functionally inert — no action needed beyond the routine npm audit fix in your next maintenance window. Per the noisgate remediation SLA for LOW findings, there is no hard deadline; document the rationale and move on to higher-priority work.

Sources

  1. GitHub Security Advisory GHSA-hrr3-gc8f-f4qj
  2. fast-uri v3.1.8 release notes
  3. fast-uri on npm
  4. GitLab Advisory Database - fast-uri
  5. Fastify ajv-compiler fast-uri integration
  6. fast-uri on Snyk
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.