CVE-2026-6322: Verified Repro With Script Download
CVE-2026-6322: fast-uri: host confusion via percent-encoded authority delimiter in normalize
CVE-2026-6322 is verified against fast-uri · npm. Affected versions: <= 3.1.1. Fixed in 3.1.2. Vulnerability class: SSRF. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00146.
What Is CVE-2026-6322?
CVE-2026-6322 (GHSA-v39h-62p7-jpjc) is a high-severity host-confusion vulnerability (CWE-436) in the npm package fast-uri, where normalize() decodes a percent-encoded authority delimiter inside the host and re-emits it raw. Pruva reproduced it (reproduction REPRO-2026-00146).
CVE-2026-6322 Severity & CVSS Score
CVE-2026-6322 is rated high severity, with a CVSS base score of 7.5 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected fast-uri Versions
fast-uri · npm versions <= 3.1.1 are affected.
How to Reproduce CVE-2026-6322
pruva-verify REPRO-2026-00146 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00146/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-6322
Reproduced by Pruva's autonomous agents — 127 tool calls over 10 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-6322
Summary
fast-uri's normalize() function decodes percent-encoded authority delimiter characters (specifically @) that appear inside the host component and then re-emits them as raw characters. When an attacker supplies a URI such as https://allowed.com%40attacker.com/, the vulnerable build decodes %40 to @, producing https://allowed.com@attacker.com/. Under RFC 3986 authority syntax, the text before @ is reinterpreted as userinfo and the effective host becomes attacker.com. This host confusion defeats any host-allowlist, SSRF guard, or redirect-validation logic built on top of normalize().
Impact
- Package:
fast-uri(npm) - Affected versions:
<= 3.1.1 - Fixed version:
3.1.2 - Risk level: High (CVSS 7.5)
- Consequences: SSRF bypass, open-redirect bypass, and general defeat of URI-based access controls that rely on normalized host values.
Root Cause
In fast-uri <= 3.1.1, the parse() function unconditionally calls unescape(parsed.host) during normalization. unescape() decodes all percent-encoded sequences, including RFC 3986 "gen-delims" such as @, :, /, ?, and #. These delimiters are structurally significant in the authority component. After decoding, serialize() / recomposeAuthority() re-emits them as raw characters, changing the parsed structure of the URI.
The fix in 3.1.2 introduces reescapeHostDelimiters() in lib/utils.js. After unescape() runs on the host, this new function scans for decoded gen-delims and re-escapes them (@ → %40, : → %3A, etc.). Additionally, normalizeStringWithStatus() detects malformed authorities or out-of-range ports and, when found, returns the original input unchanged rather than canonicalizing it into a different valid URI. The key fix commit is the v3.1.1..v3.1.2 tag range in the fastify/fast-uri repository.
Reproduction Steps
- Run
repro/reproduction_steps.sh. - The script installs
fast-uri@3.1.1(vulnerable) andfast-uri@3.1.2(fixed) into isolated scratch directories. - It invokes
normalize('https://allowed.com%40attacker.com/')against both versions and parses the resulting URI. - Expected evidence:
- Vulnerable (3.1.1): normalized URI is
https://allowed.com@attacker.com/, parsedhost=attacker.com, parseduserinfo=allowed.com. - Fixed (3.1.2): normalized URI is
https://allowed.com%40attacker.com/, parsedhost=allowed.com%40attacker.com, parseduserinfo=undefined.
- Vulnerable (3.1.1): normalized URI is
Evidence
- Log files:
logs/vuln_result.json— captured result from the vulnerable build.logs/fixed_result.json— captured result from the fixed build.
- Key excerpts from reproduction run:
VULNERABLE BUILD (3.1.1) Normalized URI: https://allowed.com@attacker.com/ Parsed host: attacker.com Parsed userinfo: allowed.com FIXED BUILD (3.1.2) Normalized URI: https://allowed.com%40attacker.com/ Parsed host: allowed.com%40attacker.com Parsed userinfo: undefined - Environment: Node.js (npm-based) running on Linux with
fast-uriinstalled from the public npm registry.
Recommendations / Next Steps
- Upgrade immediately to
fast-uri@3.1.2or later. - If upgrading is not possible: wrap
normalize()output with an additional parse-and-validate step that rejects any host containing@or other authority delimiters after normalization. - Testing recommendations: add regression tests for percent-encoded delimiters inside the host (
%40,%3A,%2F,%3F,%23) to ensure they remain escaped throughnormalize(),parse(),serialize(), andequal().
Additional Notes
- The reproduction script is idempotent: it passed two consecutive runs without modification.
- Edge cases tested implicitly by the fix include double-encoded sequences (
%2540→%40, not@) and IPv6 hosts where colon re-escaping is skipped. - The
equal()function was also hardened in3.1.2to returnfalsewhen either input is malformed, preventing accidental equivalence betweentrusted.com%40evil.comandtrusted.com@evil.com.
CVE-2026-6322 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-6322
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-6322
Upgrade fast-uri · npm to 3.1.2 or later.
FAQ: CVE-2026-6322
How does the CVE-2026-6322 host-confusion attack work?
Which fast-uri versions are affected by CVE-2026-6322, and where is it fixed?
How severe is CVE-2026-6322?
How can I reproduce CVE-2026-6322?
References for CVE-2026-6322
Authoritative sources for CVE-2026-6322 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.