---
id: "CVE-2026-110306"
kind: "vulnerability"
aliases: ["CVE-2026-110306", "GHSA-w74x-v6f9-j3xg"]
title: "fast-uri vulnerable to URI scheme spoofing via percent-encoded scheme decoding"
severity: "medium"
cvss: 6.1
epss: 0.00204
exploited: false
status: "open"
category: "package"
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-172", "cwe-180", "javascript", "node", "npm", "package", "web-apps"]
not_affected_if: ["fast-uri-not-installed", "no-user-supplied-urls-rendered", "static-export"]
published_at: "2026-10-20T07:17:08+00:00"
first_seen_at: "2026-10-23T21:45:07+00:00"
updated_at: "2026-10-23T21:57:20+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-w74x-v6f9-j3xg", "first_seen_at": "2026-10-23T21:45:07+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-110306", "first_seen_at": "2026-10-23T21:57:20+00:00"}]
---

# fast-uri vulnerable to URI scheme spoofing via percent-encoded scheme decoding

fast-uri, an npm URI parser, percent-decodes URI schemes with unescape() before checking them, so an encoded input like %6Aavascript:alert(1) comes out as a live javascript: URL. An application that filters dangerous schemes on the raw input and then renders the normalized or resolved URL can be made to run attacker script in its pages (XSS).

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- npm:fast-uri affected < 2.4.8 fixed 2.4.8
- npm:fast-uri affected >= 3.0.0, < 3.1.9 fixed 3.1.9
- npm:fast-uri affected >= 4.0.0, < 4.2.3 fixed 4.2.3

## How to check

Run `npm ls fast-uri` and check the resolved version against the affected ranges (<2.4.8, >=3.0.0 <3.1.9, >=4.0.0 <4.2.3).
Find code that calls normalize(), resolve() or equal() from fast-uri on user-supplied URLs and see whether the result is rendered or stored as a link.

## Fix

Upgrade fast-uri to 2.4.8, 3.1.9 or 4.2.3 matching your major line, then rebuild and redeploy.
Until then, reject input whose scheme part (before the first ':' and before any '/', '?' or '#') contains '%'.

## Timeline

- 2026-10-23T21:45:07+00:00 ghsa https://github.com/advisories/GHSA-w74x-v6f9-j3xg
- 2026-10-23T21:57:20+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-110306

## From the sources

### Impact

`fast-uri` percent-decodes the scheme component with the legacy global `unescape()` before validating it, so an input whose decoded scheme is a valid but dangerous token is emitted as a live scheme. RFC 3986 section 3.1 does not allow percent-encoding in a scheme, so no RFC or WHATWG parser treats such input as having that scheme, but `fast-uri` does.

For example, `normalize('%6Aavascript:alert(1)')` returns `javascript:alert(1)`, `resolve('https://a.example/', '%6Aavascript:alert(1)')` returns `javascript:alert(1)`, and `parse('%6Aavascript:alert(1)').scheme` returns `javascript`. The `%uXXXX` form (`%u006Aavascript:`) produces the same result, and `equal('%68ttp://a/', 'http://a/')` returns `true`.

An application that screens dangerous schemes on the raw input and then stores or renders `normalize(input)` or `resolve(base, input)` turns an inert string into an executable `javascript:`, `data:`, or `vbscript:` URL, a stored or reflected cross-site scripting vector in the consuming application. `equal()` also treats an encoded and a plain scheme as the same, which can bypass equality-based allowlists.

### Patches

Upgrade to `fast-uri` `2.4.8`, `3.1.9`, or `4.2.3`.

### Workarounds

Reject input whose scheme part (before the first `:`, and before any `/`, `?`, or `#`) contains `%`. Alternatively, check `parse(x).scheme` against an allowlist after normalization and use that same parsed result rather than the raw string.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
