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 resolv
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 · 8.8CVE-2026-49473CVE-2026-49473: @cedar-policy/authorization-for-expressjs Authorization Bypass via Query String
- highfast-xml-parser: Repeated DOCTYPE Declarations Reset Entity Expansion Limits
- high · 7.5CVE-2026-59892CVE-2026-59892: @opentelemetry/propagator-jaeger Denial of Service via Malformed Header
- high · 8.2svgo removeScripts Plugin XSS Bypass via Namespace Prefix and Case-Insensitive URI