Repository navigation
Permalink
Choose a base ref
{{ refName }}
default
Choose a head ref
{{ refName }}
default
Comparing changes
Choose two branches to see what’s changed or to start a new pull request.
If you need to, you can also or
learn more about diff comparisons.
Open a pull request
Create a new pull request by comparing changes across two branches. If you need to, you can also .
Learn more about diff comparisons here.
base repository: fastify/fast-uri
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.1.8
Could not load branches
Nothing to show
Loading
Could not load tags
Nothing to show
{{ refName }}
default
Loading
...
head repository: fastify/fast-uri
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.1.9
Could not load branches
Nothing to show
Loading
Could not load tags
Nothing to show
{{ refName }}
default
Loading
- 12 commits
- 9 files changed
- 4 contributors
Commits on Oct 18, 2026
-
Configuration menu - View commit details
-
Copy full SHA for 8e8e5c6 - Browse repository at this point
Copy the full SHA 8e8e5c6View commit details
Commits on Oct 19, 2026
-
fix(SEC-01): reject percent-encoded URI schemes instead of decoding them
RFC 3986 section 3.1 defines scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) and does not allow percent-encoding. The parser and serializer decoded the scheme with the deprecated `unescape()` global, which also accepts the JavaScript-only `%uXXXX` form. As a result an inert, invalid input could be turned into a live scheme by fast-uri itself: normalize('%6Aavascript:alert(1)') // 'javascript:alert(1)' normalize('%u006Aavascript:alert(1)') // 'javascript:alert(1)' resolve('http://a/b', '%6Aavascript:x') // 'javascript:x' equal('%68ttp://a/', 'http://a/') // true The scheme is now validated as-is. A scheme containing "%" is reported as malformed, so normalize() returns the input unchanged, equal() returns false and resolve()/serialize() throw. `unescape()` is no longer used. BREAKING CHANGE: percent-encoded schemes (e.g. `ht%74ps:`) are no longer decoded and are treated as malformed. (cherry picked from commit f21e3c60c35c5dc4428c6078243e9877230f8210)Configuration menu - View commit details
-
Copy full SHA for 597f254 - Browse repository at this point
Copy the full SHA 597f254View commit details -
fix(SEC-02): preserve meaning of relative references during normaliza…
…tion normalize()/serialize() applied RFC 3986 remove_dot_segments to relative-path references, which is only defined for merged target paths. This turned document-relative references into different targets: 'a/../b' became '/b' (root-relative), 'x/..' became '/', and '../x' became 'x', so equal('../x', 'x') was true. Add removeDotSegmentsRelative() in lib/utils.js and use it in serialize() when there is no scheme, no authority and the path does not start with '/'. It collapses '.' and 'seg/..' pairs, keeps leading '..' segments that cannot be collapsed, keeps a trailing-directory meaning ('a/b/..' -> 'a/'), and prefixes '.' when the result would be empty or start with an empty segment ('x/..' -> './', 'a/..//x' -> './/x'), so it never becomes root-relative, never introduces an authority and never collapses to the same-document reference ''. resolve() still accepts relative base URIs: Ajv, the main consumer, resolves schema ids against relative bases ('' / '#' / relative $id), and rejecting them breaks test/ajv.test.js. Adds test/relative-normalization-security.test.js with a seeded property test asserting resolve(b, normalize(r)) === resolve(b, r) for absolute bases and normalize() idempotence. (cherry picked from commit 0efc4dcf921a5a36ddefd8496089d3ed77ff8e47)Configuration menu - View commit details
-
Copy full SHA for b110a35 - Browse repository at this point
Copy the full SHA b110a35View commit details -
Configuration menu - View commit details
-
Copy full SHA for eb483b5 - Browse repository at this point
Copy the full SHA eb483b5View commit details -
Configuration menu - View commit details
-
Copy full SHA for d86a8d2 - Browse repository at this point
Copy the full SHA d86a8d2View commit details -
fix(SEC-03): reject non reg-name characters in domain hosts
For domain-host schemes, `canonicalizeHost()` passed the host straight to `new URL('http://' + host)` and used the returned hostname, without checking that the WHATWG parser had read the whole input as a host. Because the RFC 3986 parse lets "@" into the host group, and WHATWG strips TAB/LF/CR, the reported authority was silently rewritten by a second parser, with no error: parse('http://a@[email protected]/').host // 'evil.com' ("b" dropped) normalize('http://ev\til.com/p') // 'http://evil.com/p' equal('http://ev\til.com/', 'http://evil.com/') // true resolve('http://x/', '//a@[email protected]/p') // 'http://[email protected]/p' Domain hosts containing an ASCII character outside the RFC 3986 reg-name set (unreserved, sub-delims, pct-encoded) now fail closed with 'URI host is malformed.', regardless of `unicodeSupport`. `resolve()` checks the final host once the effective scheme is known and throws, including for percent-encoded hosts that previously bypassed the error. As a further safeguard, the WHATWG result is accepted only when it contains nothing but a hostname (no userinfo, port, path, query or fragment). Schemes without domain hosts keep their existing RFC 3986 encoding behaviour. (cherry picked from commit 07dfb95f02db31e8c241a13c10b6b5d51b27fa16)Configuration menu - View commit details
-
Copy full SHA for ddfc6a5 - Browse repository at this point
Copy the full SHA ddfc6a5View commit details -
Configuration menu - View commit details
-
Copy full SHA for 745183c - Browse repository at this point
Copy the full SHA 745183cView commit details -
fix: escape a first-segment colon in suffix references
A suffix reference emits no scheme token, so its first path segment must not contain a bare colon or the output reparses as an absolute URI. Ref: GHSA-333x-w4r6-6crp
Configuration menu - View commit details
-
Copy full SHA for 39e6493 - Browse repository at this point
Copy the full SHA 39e6493View commit details -
Configuration menu - View commit details
-
Copy full SHA for 54c30f7 - Browse repository at this point
Copy the full SHA 54c30f7View commit details -
Configuration menu - View commit details
-
Copy full SHA for 9eb8759 - Browse repository at this point
Copy the full SHA 9eb8759View commit details -
Configuration menu - View commit details
-
Copy full SHA for a1d0da2 - Browse repository at this point
Copy the full SHA a1d0da2View commit details -
Configuration menu - View commit details
-
Copy full SHA for 0def703 - Browse repository at this point
Copy the full SHA 0def703View commit details
Loading
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v3.1.8...v3.1.9