{"id":"CVE-2026-110180","kind":"vulnerability","aliases":["CVE-2026-110180","GHSA-wjr9-j795-jxcr"],"related":[],"title":"fast-uri vulnerable to host confusion via unchecked WHATWG host canonicalization","description":"### Impact\n\n`fast-uri` versions `>= 2.4.2, <= 2.4.7`, `>= 3.1.3, <= 3.1.8`, and `>= 4.0.1, <= 4.2.2` can silently rewrite the host of an HTTP-family URL (`http`, `https`, `ws`, `wss`, or any scheme with `domainHost: true`). For those schemes `canonicalizeHost()` passes the parsed host to the WHATWG `URL` parser and adopts its `.hostname` without checking that the parser read the whole input as a host. RFC 3986 permits `@` inside the host group and the WHATWG parser strips TAB, LF, and CR, so the authority `fast-uri` reports is rewritten by that second parser with no `error` set: data before an `@` is dropped and whitespace is removed.\n\nFor example, `fast-uri` parses `http://a@b@evil.example/` to host `evil.example` (dropping the `b` segment), and a host containing a raw TAB, CR, or LF has those characters stripped. `equal()` then treats a whitespace-smuggled host as the same as the clean one, and `resolve()` rewrites the authority the same way.\n\nApplications that use `fast-uri` to enforce host-based policy (denylists, loopback filtering, redirect validation, outbound proxy routing) on one representation, such as the raw input, see a policy/use desync: the canonical host `fast-uri` returns differs from what was checked, and traffic can be steered to an unintended destination.\n\n### Patches\n\nUpgrade to `fast-uri` `2.4.8`, `3.1.9`, or `4.2.3`.\n\n### Workarounds\n\nReject URIs whose authority contains more than one `@`, or contains TAB, CR, or LF, before calling `fast-uri`. Alternatively, treat any non-empty `parse(x).error` as fatal, and compare hosts only from the same `parse()` result.","summary":"fast-uri rewrites the host of http, https, ws and wss URLs without checking the whole input was a valid host, so an authority like 'a@b@evil.example' or one with a hidden TAB, CR or LF is silently turned into a different host. An application that checks hosts on one parse and connects using another can be steered to an unintended destination.","severity":"medium","cvss":4.8,"epss":0.00208,"exploited":false,"exploited_at":null,"products":[{"name":"fast-uri","fixed":["2.4.8"],"affected":">= 2.4.2, < 2.4.8","ecosystem":"npm"},{"name":"fast-uri","fixed":["3.1.9"],"affected":">= 3.1.3, < 3.1.9","ecosystem":"npm"},{"name":"fast-uri","fixed":["4.2.3"],"affected":">= 4.0.1, < 4.2.3","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["cwe-20","cwe-436","node.js","npm","package","ssrf-defense","url-validation"],"not_affected_if":["fast-uri-not-installed","fast-uri-outside-2.4.2-to-4.2.2-range","no-host-based-policy"],"how_to_check":"Run: npm ls fast-uri\nLook for fast-uri versions >= 2.4.2 <= 2.4.7, >= 3.1.3 <= 3.1.8, or >= 4.0.1 <= 4.2.2 in the output.\nCheck code that uses fast-uri for host allowlists, denylists, redirect validation or proxy routing.","fix":"Upgrade fast-uri to 2.4.8, 3.1.9, or 4.2.3 (match your major line).\nIf you cannot upgrade, reject URIs with more than one '@' or any TAB, CR or LF in the authority before calling fast-uri.","status":"open","published_at":"2026-10-20T07:17:08+00:00","first_seen_at":"2026-10-23T21:39:59+00:00","triaged_at":"2026-10-23T21:41:16+00:00","updated_at":"2026-10-23T21:57:20+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-23T21:41:16Z","model":"claude-haiku-5-5","output":{"fix":"Upgrade fast-uri to 2.4.8, 3.1.9, or 4.2.3 (match your major line).\nIf you cannot upgrade, reject URIs with more than one '@' or any TAB, CR or LF in the authority before calling fast-uri.","reach":"network","impact":"medium","summary":"fast-uri rewrites the host of http, https, ws and wss URLs without checking the whole input was a valid host, so an authority like 'a@b@evil.example' or one with a hidden TAB, CR or LF is silently turned into a different host. An application that checks hosts on one parse and connects using another can be steered to an unintended destination.","category":"package","who_cares":["npm","node.js","url-validation","ssrf-defense"],"confidence":0.8,"needs_auth":"no","worst_case":"Host policy bypassed, requests steered to attacker-chosen destination","analyst_note":"","how_to_check":"Run: npm ls fast-uri\nLook for fast-uri versions >= 2.4.2 <= 2.4.7, >= 3.1.3 <= 3.1.8, or >= 4.0.1 <= 4.2.2 in the output.\nCheck code that uses fast-uri for host allowlists, denylists, redirect validation or proxy routing.","needs_analyst":false,"not_affected_if":["fast-uri-not-installed","fast-uri-outside-2.4.2-to-4.2.2-range","no-host-based-policy"],"user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"medium"},"cost_usd":0.000617,"input_tokens":3472,"output_tokens":539,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-110180':15A,23A '-20':34B '-2026':14A,22A '-436':36B '2.4.2':114C '2.4.7':115C '2.4.8':324C '3.1.3':116C '3.1.8':117C '3.1.9':325C '3986':172C '4.0.1':119C '4.2.2':120C '4.2.3':327C 'adopt':156C 'altern':348C 'anoth':101B 'applic':91B,265C 'author':70B,189C,261C,332C 'b':226C 'b@evil.example':73B,220C 'base':275C 'call':344C 'canon':298C 'canonic':12A 'canonicalizehost':145C 'charact':240C 'check':60B,93B,160C,308C 'clean':255C 'compar':360C 'confus':7A 'connect':99B 'contain':231C,333C,338C 'cr':80B,186C,235C,340C 'cve':13A,21A 'cwe':33B,35B 'data':204C 'defens':42B 'denylist':277C 'destin':108B,317C 'desync':296C 'differ':88B,304C 'domainhost':140C 'drop':208C,224C 'empti':353C 'enforc':272C 'equal':242C 'error':202C,356C 'evil.example':223C 'exampl':214C 'famili':130C 'fast':2A,25A,28A,31A,47B,111C,191C,216C,269C,301C,322C,346C 'fast-uri':1A,24A,27A,30A,46B,110C,190C,215C,268C,300C,321C,345C 'fatal':358C 'filter':279C 'ghsa':17A 'ghsa-wjr9-j795-jxcr':16A 'group':177C 'hidden':78B 'host':6A,11A,51B,67B,89B,94B,125C,149C,170C,176C,222C,230C,249C,274C,299C,361C 'host-bas':273C 'hostnam':158C 'http':53B,129C,132C 'http-famili':128C 'https':54B,133C 'impact':109C 'input':63B,167C,292C 'insid':174C 'j795':19A 'jxcr':20A 'lf':82B,184C,237C,342C 'like':71B 'loopback':278C 'node.js':37B 'non':352C 'non-empti':351C 'npm':38B 'one':75B,96B,256C,286C,336C 'outbound':282C 'packag':39B 'pars':97B,148C,218C,354C,366C 'parser':154C,163C,181C,199C 'pass':146C 'patch':318C 'permit':173C 'polici':276C 'policy/use':295C 'proxi':283C 'raw':233C,291C 'read':164C 'redirect':280C 'reject':329C 'remov':212C 'report':193C 'represent':287C 'resolv':258C 'result':367C 'return':303C 'rewrit':49B,123C,259C 'rewritten':195C 'rfc':171C 'rout':284C 'scheme':138C,144C 'second':198C 'see':293C 'segment':227C 'set':203C 'silent':84B,122C 'smuggl':248C 'ssrf':41B 'ssrf-defens':40B 'steer':104B,313C 'strip':182C,241C 'tab':79B,183C,234C,339C 'traffic':310C 'treat':244C,349C 'true':141C 'turn':85B 'uncheck':9A 'unintend':107B,316C 'upgrad':319C 'uri':3A,26A,29A,32A,48B,112C,192C,217C,270C,302C,323C,330C,347C 'url':44B,58B,131C,153C 'url-valid':43B 'use':100B,267C 'valid':45B,66B,281C 'version':113C 'via':8A 'vulner':4A 'way':264C 'whatwg':10A,152C,180C 'whitespac':210C,247C 'whitespace-smuggl':246C 'whole':62B,166C 'whose':331C 'without':59B,159C 'wjr9':18A 'workaround':328C 'ws':55B,134C 'wss':57B,135C 'x':355C","nicknames":[],"mitigations":[],"who_affected":null,"tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-20T07:17:08+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-wjr9-j795-jxcr","url":"https://github.com/advisories/GHSA-wjr9-j795-jxcr","severity":"medium","published_at":"2026-10-23T21:37:59+00:00","modified_at":"2026-10-23T21:38:02+00:00","first_seen_at":"2026-10-23T21:39:59+00:00","fetched_at":"2026-10-23T21:39:59+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-110180","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-110180","severity":null,"published_at":"2026-10-20T07:17:08+00:00","modified_at":"2026-10-20T20:06:37+00:00","first_seen_at":"2026-10-23T21:57:20+00:00","fetched_at":"2026-10-23T22:28:57+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}