high · 7.5CVE-2026-75931Sep 2, 2026

CVE-2026-75931: fast-uri Host Confusion via Skipped IDN Canonicalization on Scheme-Relative References

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

fast-uri skips Unicode hostname conversion when resolving scheme-relative URLs like //attacker.com against a real base, so an app can allowlist one host and silently reach a completely different one.

Packagefast-uri
Ecosystemnpm
Affected>= 2.4.2, < 2.4.5
Fixed in2.4.5
CVE-2026-75931: fast-uri Host Confusion via Skipped IDN Canonicalization on Scheme-Relative References

The problem

fast-uri added IDN canonicalization (ASCII punycode conversion) as the fix for CVE-2026-13676, but only triggered it when the input URI carried an explicit scheme.

When resolve() processes a scheme-relative reference (//unicode-host/path) against a scheme-bearing base, the effective scheme is known but the IDN step is bypassed entirely. The host is emitted verbatim in Unicode form. An application that checks the resolved host for policy (allowlist, SSRF guard, redirect validation) sees the raw Unicode string, while Node's native WHATWG URL and fetch() canonicalize that same string to a different ASCII address before making the actual request.

Proof of concept

A working proof-of-concept for CVE-2026-75931 in fast-uri, with the exact payload below.

javascript
const uri = require('fast-uri')

// Scheme-relative reference with a Unicode/IDN loopback host.
// The base carries an explicit scheme (http) so the effective scheme IS known.
const resolved = uri.resolve(
  'http://allowed.example.com',
  '//127。0。0。1/admin'
)
// Vulnerable versions emit:
//   "http://127。0。0。1/admin"  <-- host NOT canonicalized
//
// App allowlist check: resolved host is "127。0。0。1" -> passes (not "127.0.0.1")
// fetch(resolved) in Node.js:          WHATWG URL normalizes to 127.0.0.1 -> loopback reached
console.log(resolved)
// => "http://127。0。0。1/admin"   (before patch)
// => throws / host canonicalized to "127.0.0.1" (after patch 2.4.5)

The root cause is a CWE-436 Interpretation Conflict: fast-uri and Node's WHATWG URL engine parse the same byte sequence into different effective hosts. The prior fix for CVE-2026-13676 gated domainToASCII() on scheme presence in the *input string*, not on the *effective* scheme after resolution.

Scheme-relative references inherit their scheme from the base during resolve(), so the guard was never entered. The patch in 2.4.5 moves IDN canonicalization to fire once the effective scheme is determined inside resolveComponents(), and fails closed (errors out) if a raw non-ASCII host cannot be converted, rather than returning it verbatim.

The fix

Upgrade to fast-uri 2.4.5 (v2.x), 3.1.6 (v3.x), or 4.1.3 (v4.x). If an immediate upgrade is blocked, pre-resolve scheme-relative references against a trusted scheme-bearing base before passing them to any host-policy or origin check, ensuring the scheme is explicit in the input string.

Reported by celinke97.

References: [1][2][3][4][5][6]

Related research