Skip to content

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.

REPRO-2026-00146 fast-uri · npm SSRF May 22, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
7.5
Reproduced in
10m 18s
Tool calls
127
Spend
$1.03
01 · Overview

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).

02 · Severity & CVSS

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 threat level
7.5 / 10 CVSS base
Weakness CWE-436 (Interpretation Conflict)

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected fast-uri Versions

fast-uri · npm versions <= 3.1.1 are affected.

How to Reproduce CVE-2026-6322

$ pruva-verify REPRO-2026-00146
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00146/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

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 423 events · 127 tool calls · 10 min
10 minDuration
127Tool calls
98Reasoning steps
423Events
Agent activity over 10 min
Support
25
Repro
100
Variant
294
0:0010:18

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

  1. Run repro/reproduction_steps.sh.
  2. The script installs fast-uri@3.1.1 (vulnerable) and fast-uri@3.1.2 (fixed) into isolated scratch directories.
  3. It invokes normalize('https://allowed.com%40attacker.com/') against both versions and parses the resulting URI.
  4. Expected evidence:
    • Vulnerable (3.1.1): normalized URI is https://allowed.com@attacker.com/, parsed host = attacker.com, parsed userinfo = allowed.com.
    • Fixed (3.1.2): normalized URI is https://allowed.com%40attacker.com/, parsed host = allowed.com%40attacker.com, parsed userinfo = undefined.

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-uri installed from the public npm registry.

Recommendations / Next Steps

  • Upgrade immediately to fast-uri@3.1.2 or 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 through normalize(), parse(), serialize(), and equal().

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 in 3.1.2 to return false when either input is malformed, preventing accidental equivalence between trusted.com%40evil.com and trusted.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.

Event 1/40
0:000:46
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-6322 · cve-2026
0:09
0:11
0:12
web search
0:14
0:15
web search
0:22
0:24
0:25
0:26
web search
0:42
0:42
extract_facts
no facts extracted
0:42
0:42
0:42
supportrepro
0:44
0:44
0:44
0:44
0:46
0:46

Artifacts and Evidence for CVE-2026-6322

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2026-6322

Upgrade fast-uri · npm to 3.1.2 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-6322 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-6322

How does the CVE-2026-6322 host-confusion attack work?

An attacker supplies a host string combining an allowed domain, an encoded @ (%40), and a second domain, for example allowed.com%40attacker.com. The vulnerable normalize() decodes %40 to a raw @, 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, while any host-allowlist, SSRF guard, or redirect-validation check built on the normalized value still sees allowed.com.

Which fast-uri versions are affected by CVE-2026-6322, and where is it fixed?

Versions <= 3.1.1 are affected. It is fixed in 3.1.2, which introduces reescapeHostDelimiters() in lib/utils.js to re-escape decoded gen-delims like @ back to %40 after unescape() runs on the host.

How severe is CVE-2026-6322?

It is rated high severity. It defeats any host-allowlist, SSRF guard, or redirect-validation logic built on top of normalize(), since validation code sees the allowed domain while the effective network destination is attacker-controlled.

How can I reproduce CVE-2026-6322?

Download the verified script from this page and run it in an isolated environment against fast-uri <= 3.1.1. It normalizes a URI such as https://allowed.com%40attacker.com/ and shows the resulting host resolving to attacker.com despite passing a check for allowed.com, then confirms 3.1.2 re-escapes the delimiter and preserves the correct host.
11 · References

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.