{"id":"CVE-2026-110725","kind":"vulnerability","aliases":["CVE-2026-110725","GHSA-333x-w4r6-6crp"],"related":[],"title":"fast-uri vulnerable to scheme injection via an unescaped first-segment colon in suffix references","description":"### Impact\n\n`fast-uri`'s `serialize()`, `normalize()`, and `resolve()`, when called with the non-default option `reference: 'suffix'` on a reference that has no authority, emit a relative reference whose first path segment contains a bare colon without escaping it. RFC 3986 section 3.3 requires the first segment of a `path-noscheme` reference not to contain a colon, precisely because a bare colon makes the string reparse as an absolute URI with a scheme. `fast-uri`'s default serialization escapes that colon, but the suffix path does not.\n\nFor example, `normalize('javascript:alert(1)', { reference: 'suffix' })` returns `javascript:alert(1)`, which reparses as a live `javascript:` scheme; `data:` and `vbscript:` behave the same.\n\nApplications that serialize or normalize a relative reference with `reference: 'suffix'` and then treat the result as a URI can turn inert input into a live `javascript:`, `data:`, or `vbscript:` URL (a cross-site scripting vector), and `equal()` can conflate a scheme-bearing reference with a relative one. Exposure is limited to applications that use the non-default `reference: 'suffix'` option.\n\n### Patches\n\nUpgrade to `fast-uri` `2.4.8`, `3.1.9`, or `4.2.3`.\n\n### Workarounds\n\nDo not use the `reference: 'suffix'` option on untrusted input. If suffix output is required, percent-encode a colon in the first path segment of the result before treating it as a URI.","summary":"fast-uri, an npm URI parsing library, fails to escape a colon in the first path segment when the non-default reference: 'suffix' option is used, so a relative reference like javascript:alert(1) reparses as a live javascript: URL. An attacker who controls the input that the application serializes or normalizes can produce a cross-site scripting vector.","severity":"low","cvss":3.7,"epss":0.00254,"exploited":false,"exploited_at":null,"products":[{"name":"fast-uri","fixed":["2.4.8"],"affected":"< 2.4.8","ecosystem":"npm"},{"name":"fast-uri","fixed":["3.1.9"],"affected":">= 3.0.0, < 3.1.9","ecosystem":"npm"},{"name":"fast-uri","fixed":["4.2.3"],"affected":">= 4.0.0, < 4.2.3","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["cwe-116","cwe-41","frontend","javascript","node","npm","package"],"not_affected_if":["default-config","no-suffix-option","not-on-fast-uri-2.4.8-or-later"],"how_to_check":"Run: grep -rn \"reference: *'suffix'\" node_modules-free source (search your own code for reference: 'suffix') and check the installed version with npm ls fast-uri","fix":"Upgrade fast-uri to 2.4.8, 3.1.9, or 4.2.3 depending on the major line in use, or stop using reference: 'suffix' on untrusted input.\nIf suffix output is required, percent-encode a colon in the first path segment before treating the result as a 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:20+00:00","updated_at":"2026-10-23T21:57:20+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-23T21:41:20Z","model":"claude-haiku-5-5","output":{"fix":"Upgrade fast-uri to 2.4.8, 3.1.9, or 4.2.3 depending on the major line in use, or stop using reference: 'suffix' on untrusted input.\nIf suffix output is required, percent-encode a colon in the first path segment before treating the result as a URI.","reach":"unknown","impact":"medium","summary":"fast-uri, an npm URI parsing library, fails to escape a colon in the first path segment when the non-default reference: 'suffix' option is used, so a relative reference like javascript:alert(1) reparses as a live javascript: URL. An attacker who controls the input that the application serializes or normalizes can produce a cross-site scripting vector.","category":"package","who_cares":["npm","node","javascript","frontend"],"confidence":0.8,"needs_auth":"unknown","worst_case":"Attacker-controlled input becomes a live javascript: URL, enabling cross-site scripting.","analyst_note":"","how_to_check":"Run: grep -rn \"reference: *'suffix'\" node_modules-free source (search your own code for reference: 'suffix') and check the installed version with npm ls fast-uri\nunknown\nunknown","needs_analyst":false,"not_affected_if":["default-config","no-suffix-option","not-on-fast-uri-2.4.8-or-later"],"user_interaction":"unknown","needs_special_setup":"yes","severity_if_unknown":"low"},"cost_usd":0.00058,"input_tokens":3334,"output_tokens":494,"severity_before":"low"},"analyst_status":null,"analyst_note":null,"search":"'-110725':20A,28A '-116':39B '-2026':19A,27A '-41':41B '1':82B,205C,211C '2.4.8':295C '3.1.9':296C '3.3':153C '333x':23A '3986':151C '4.2.3':298C '6crp':25A 'absolut':180C 'alert':81B,204C,210C 'applic':97B,225C,279C 'attack':90B 'author':134C 'bare':145C,172C 'bear':269C 'behav':222C 'call':119C 'colon':14A,59B,146C,168C,173C,193C,319C 'conflat':265C 'contain':143C,166C 'control':92B 'cross':105B,258C 'cross-sit':104B,257C 'cve':18A,26A 'cwe':38B,40B 'data':219C,252C 'default':69B,124C,189C,285C 'emit':135C 'encod':317C 'equal':263C 'escap':57B,148C,191C 'exampl':201C 'exposur':275C 'fail':55B 'fast':2A,30A,33A,36A,48B,111C,186C,293C 'fast-uri':1A,29A,32A,35A,47B,110C,185C,292C 'first':12A,62B,140C,156C,322C 'first-seg':11A 'frontend':42B 'ghsa':22A 'ghsa-333x-w4r6-6crp':21A 'impact':109C 'inert':246C 'inject':7A 'input':94B,247C,309C 'javascript':43B,80B,87B,203C,209C,217C,251C 'librari':54B 'like':79B 'limit':277C 'live':86B,216C,250C 'make':174C 'node':44B 'non':68B,123C,284C 'non-default':67B,122C,283C 'normal':100B,115C,202C,229C 'noschem':162C 'npm':45B,51B 'one':274C 'option':72B,125C,288C,306C 'output':312C 'packag':46B 'pars':53B 'patch':289C 'path':63B,141C,161C,197C,323C 'path-noschem':160C 'percent':316C 'percent-encod':315C 'precis':169C 'produc':102B 'refer':17A,70B,78B,126C,130C,138C,163C,206C,232C,234C,270C,286C,304C 'relat':77B,137C,231C,273C 'repars':83B,177C,213C 'requir':154C,314C 'resolv':117C 'result':240C,327C 'return':208C 'rfc':150C 'scheme':6A,184C,218C,268C 'scheme-bear':267C 'script':107B,260C 'section':152C 'segment':13A,64B,142C,157C,324C 'serial':98B,114C,190C,227C 'site':106B,259C 'string':176C 'suffix':16A,71B,127C,196C,207C,235C,287C,305C,311C 'treat':238C,329C 'turn':245C 'unescap':10A 'untrust':308C 'upgrad':290C 'uri':3A,31A,34A,37A,49B,52B,112C,181C,187C,243C,294C,333C 'url':88B,255C 'use':74B,281C,302C 'vbscript':221C,254C 'vector':108B,261C 'via':8A 'vulner':4A 'w4r6':24A 'whose':139C 'without':147C 'workaround':299C","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:N/I:L/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-333x-w4r6-6crp","url":"https://github.com/advisories/GHSA-333x-w4r6-6crp","severity":"low","published_at":"2026-10-23T21:36:40+00:00","modified_at":"2026-10-23T21:36:41+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-110725","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-110725","severity":null,"published_at":"2026-10-20T07:17:08+00:00","modified_at":"2026-10-20T20:17:16+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"}