{
  "ticket_id": "CVE-2026-6321",
  "code_root": "external/fast-uri",
  "source": {
    "type": "cve",
    "cve_id": "CVE-2026-6321",
    "advisory_id": "GHSA-q3j6-qgpj-74h6",
    "advisory_url": "https://github.com/fastify/fast-uri/security/advisories/GHSA-q3j6-qgpj-74h6",
    "vendor": "fastify",
    "product": "fast-uri",
    "repo": "https://github.com/fastify/fast-uri"
  },
  "facts": {
    "cve_id": "CVE-2026-6321",
    "advisory_id": "GHSA-q3j6-qgpj-74h6",
    "issue_summary": "Path traversal in fast-uri. normalize() and equal() decode percent-encoded path separators and dot segments BEFORE applying RFC 3986 dot-segment removal. An encoded sequence such as %2e%2e%2f is therefore decoded into a literal '../' and is then treated as a real dot segment, so two distinct URIs collapse onto the same normalized path. This bypasses path-prefix allowlist checks built on top of normalize()/equal().",
    "vulnerability_type": "Path Traversal",
    "suspected_cwe": ["CWE-22"],
    "affected_versions": "<= 3.1.0",
    "fixed_versions": ["3.1.1"],
    "reproduce_version": "3.1.0",
    "verify_fixed_version": "3.1.1",
    "repo_url": "https://github.com/fastify/fast-uri.git",
    "code_root": "external/fast-uri",
    "ecosystem": "npm",
    "package": "fast-uri",
    "affected_functions": ["normalize", "equal"],
    "install_recipe": "In a scratch directory run `npm install fast-uri@3.1.0` (vulnerable) or `npm install fast-uri@3.1.1` (fixed). The published npm tarball is the canonical artifact; git tags v3.1.0 / v3.1.1 on the repo are equivalent.",
    "attacker_access": "Any code path that forwards an attacker-influenced URI string into fast-uri's normalize() or equal() and then uses the result for a path-prefix allowlist decision.",
    "exploit_outline": "Call normalize() on a URL whose path contains percent-encoded traversal, e.g. an encoded `%2e%2e%2f` sequence. The vulnerable build decodes the encoded separators/dot-segments first, so the resulting normalized path walks above the intended prefix.",
    "vulnerable_indicator": "The normalized path string returned by normalize() escapes the intended path prefix (the encoded `..` is collapsed into a real parent-directory traversal).",
    "fixed_indicator": "In 3.1.1 normalize() keeps the path confined to the intended prefix; the returned normalized string differs from the vulnerable build's output.",
    "reproduction_requirements": "Node.js (any maintained LTS) plus the fast-uri package at the specified version. No network service, database, browser, or OS-specific behavior required - the difference is observable purely in-process by comparing the string returned by normalize().",
    "notes": "Do not invent specific version numbers or commit hashes beyond those stated here. The Pruva repro agent reads the patch diff itself (git diff v3.1.0..v3.1.1) to confirm the root cause and guard."
  }
}
