← Back to Feed CACHED · 2026-09-15 11:44:59 · CACHE_KEY CVE-2026-86818
CVE-2026-86818 · CWE-172 · Disclosed 2026-09-15

fast-uri vulnerable to mailto header injection via percent-encoded field-name desynchronization

ASSESSED — NOISGATE
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Someone left a decoder ring in the mailroom, but almost nobody uses that mailroom

CVE-2026-86818 is a desynchronization flaw in fast-uri's mailto scheme handling, affecting only versions 4.1.3 and 4.1.4. The parser compares field names (like to, subject, body) while they are still percent-encoded (%74o, %73ubject, %62ody), but decodes them before storing. When the URI is re-serialized, the decoded names are emitted as raw characters — smuggling additional recipients, subjects, or body content past any validation that ran against the parsed representation. The fix landed in v4.1.5.

The vendor's MEDIUM / 4.8 rating is *generous* for the real-world population at risk. The CVSS vector (AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N) already encodes High attack complexity and only Low confidentiality/integrity impact with zero availability impact. What the score doesn't capture is the ultra-narrow version window (two patch releases) and the exotic prerequisite: your application must parse untrusted mailto: URIs with fast-uri, make an allowlist or display decision on the parsed to field, then re-serialize and hand the string to a mail-sending path. In server-side Node.js — where fast-uri lives as a Fastify/AJV transitive dependency for *HTTP* URI validation — this pattern is vanishingly rare. The vendor score overstates practical risk for the overwhelming majority of the ~99 million weekly installs.

"Narrow version window and niche mailto parsing pattern make this a backlog item, not an emergency."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Attacker crafts a poisoned mailto URI

The attacker constructs a mailto: URI where header field names are percent-encoded (e.g., %[email protected] instead of [email protected]). This is syntactically valid per RFC 6068 but exploits the parser's failure to normalize field names before comparison.
Conditions required:
  • Attacker can supply an untrusted URI to the target application
Where this breaks in practice:
  • Application must accept and process mailto: URIs specifically, not just HTTP/HTTPS URIs
  • Most fast-uri consumers (Fastify, AJV) never invoke the mailto parser
STEP 02

Application parses and trusts the result

The application calls fast-uri.parse() on the attacker-supplied mailto URI and inspects the parsed to field or header map to make a security-relevant decision — for example, checking the recipient against an allowlist, or displaying the parsed address to the user for confirmation. Because the encoded field names don't match the expected literal strings, the injected fields may be invisible to validation logic.
Conditions required:
  • Application uses fast-uri v4.1.3 or v4.1.4
  • Application performs a trust decision (allowlist, display, logging) on parsed mailto fields before re-serialization
Where this breaks in practice:
  • This parse-decide-reserialize pattern for mailto is extremely uncommon in Node.js backends
  • Most mailto link handling happens client-side in browsers, which have their own parsers
STEP 03

Re-serialization emits decoded field names

When the application calls fast-uri.serialize() on the parsed result, the now-decoded field names (to, subject, body) are written back as raw characters. The serialized URI now contains header fields the original validation did not account for. The attacker has injected additional recipients, a controlled subject line, or arbitrary body content into the mailto URI.
Conditions required:
  • Application re-serializes the parsed result and passes it to a mail client, window.open(), or server-side send path
Where this breaks in practice:
  • Server-side mailto send paths are rare — most applications use SMTP libraries directly, not mailto URIs
  • The blast radius is a single crafted email, not code execution or persistent compromise
Detection/coverage: Static analysis scanning for fast-uri imports combined with serialize() calls on mailto-scheme inputs could flag this pattern, but no known scanner rule exists yet.
STEP 04

Mail client processes the smuggled headers

The downstream mail client (Thunderbird, Outlook, a webmail compose window, or a server-side mailer that accepts mailto URIs) processes the serialized URI and populates the injected To, Subject, and Body fields. The attacker achieves unauthorized email recipient injection or content spoofing.
Conditions required:
  • Downstream mail handler honors mailto header fields from the URI
Where this breaks in practice:
  • Many modern mail clients strip or ignore non-standard mailto headers
  • Impact is limited to email content manipulation — no RCE, no persistence, no lateral movement
Detection/coverage: Email gateway DLP or recipient validation rules may catch unexpected recipients added via this vector.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNone known. No reports from any threat intelligence feed, no mention in CISA KEV.
Proof of ConceptThe GHSA-jvvf-x445-j334 advisory includes a conceptual description of the encode/decode desync. No standalone weaponized PoC repository identified.
EPSS ScoreNot yet scored (CVE too recent). Expected to land in the bottom quartile given the niche attack surface.
KEV StatusNot listed. No CISA KEV entry as of 2026-09-15.
CVSS VectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N — Network-reachable but High complexity, no privileges needed, no user interaction, Unchanged scope, Low C/I, zero availability. The AC:H is doing heavy lifting here.
Affected Versionsfast-uri >= 4.1.3, < 4.1.5 — only two point releases in the v4 line. The v2.x and v3.x lines are not affected by this specific CVE.
Fixed Version4.1.5 (4.1.5" target="_blank" rel="noopener">release notes)
Scanning / Exposure~99 million weekly npm downloads, but the vast majority are transitive via Fastify/AJV for HTTP URI validation. The population actually invoking mailto parsing is a tiny fraction — likely < 0.1% of the install base.
Disclosure Date2026-09-15 (published same day as advisory)
Reportermcollina (Matteo Collina, Fastify maintainer) — self-reported by the project team.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (3.0/10)

The single most decisive factor is the vanishingly small exposed population: while fast-uri has ~99M weekly downloads, the mailto parse-reserialize pattern required for exploitation applies to an estimated <0.1% of consumers, and the affected version window spans only two releases (4.1.3–4.1.4). Impact is capped at email content manipulation with no path to code execution or persistence.

HIGH Vulnerability mechanics and affected version range
HIGH Patch availability (v4.1.5 released)
MEDIUM Estimate of real-world mailto usage in fast-uri consumers
LOW EPSS score (not yet published)

Why this verdict

  • Ultra-narrow version window: Only v4.1.3 and v4.1.4 are affected — two patch releases in a single major line. The v2.x and v3.x lines (which represent the majority of the npm install base via older Fastify/AJV pinnings) are not vulnerable.
  • Exotic prerequisite chain: Exploitation requires a specific 4-step pattern: accept untrusted mailto URI → parse with fast-uri → make trust decision on parsed fields → re-serialize and hand to a mail sender. Each step is individually uncommon in server-side Node.js; the conjunction is vanishingly rare.
  • Low blast radius: Even when fully exploited, the outcome is unauthorized email recipient injection or content manipulation. There is no code execution, no persistence, no privilege escalation, and no lateral movement.
  • Role multiplier: fast-uri is a URI parsing library, not a high-value-role component. (a) *Low-value role*: dev tooling, test suites — no impact. (b) *Typical role*: Fastify HTTP servers using AJV validation — mailto parser never invoked, chain does not succeed. (c) *High-value role*: Even if fast-uri were used in a CI/CD pipeline or identity provider's backend, the mailto-specific attack path does not yield fleet compromise, domain takeover, or supply-chain pivot — it yields a single crafted email. No high-value-role floor applies.
  • AC:H already baked in: The vendor's own CVSS vector acknowledges High attack complexity, which further suppresses real-world exploitability.

Why not higher?

The vulnerability is network-reachable and requires no authentication or user interaction, which normally argues for at least MEDIUM. However, the two-release version window, the mailto-specific prerequisite (irrelevant to >99.9% of consumers), and the email-only impact ceiling collectively mean the *real* population at risk is negligible. No high-value-role floor is triggered because the worst-case outcome is email content manipulation, not fleet or identity compromise.

Why not lower?

We do not drop to IGNORE because the vulnerability is technically real, the advisory is from a credible source (the Fastify maintainer), and a small number of applications *could* use the mailto parse-reserialize pattern. For the handful of teams that do, the integrity impact is genuine — an attacker can add recipients to outbound emails, which may have compliance or data-leak implications in regulated environments.

05 · Compensating Control

What to do — in priority order.

  1. Pin or upgrade fast-uri to ≥ 4.1.5 in your lockfile — This is a one-line npm audit fix or lockfile pin. Since this is a LOW verdict, there is no noisgate mitigation SLA — treat this as backlog hygiene and roll it into your next dependency update cycle.
  2. Audit codebase for mailto URI parsing via fast-uri — Search for parse() calls on user-supplied mailto: URIs followed by serialize(). If you find none (likely), this CVE has zero applicability to your deployment and you can deprioritize further.
  3. Validate recipients after serialization, not just after parsing — If you do process mailto URIs, add a post-serialization check that re-parses the output and confirms the recipient list matches expectations. This breaks the desync chain regardless of fast-uri version.
What doesn't work
  • WAF rules on mailto URIs — WAFs operate on HTTP request/response bodies and headers; they have no visibility into how an application internally parses and re-serializes mailto URIs after ingestion.
  • npm audit severity filtering at MEDIUM — If your pipeline blocks on MEDIUM+ findings from npm audit, this CVE will fire. Consider suppressing with a documented rationale rather than upgrading under emergency pressure.
06 · Verification

Crowdsourced verification payload.

Run this on any machine with node (v16+) and access to the project's node_modules. Invoke: bash check_cve_2026_86818.sh /path/to/project. No special privileges required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_86818.sh — Detect fast-uri versions vulnerable to CVE-2026-86818
# Usage: bash check_cve_2026_86818.sh /path/to/node/project
# Exit codes: 0 = PATCHED/NOT_AFFECTED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

PROJECT_DIR="${1:-.}"

if [ ! -d "$PROJECT_DIR/node_modules" ]; then
  echo "UNKNOWN — no node_modules found at $PROJECT_DIR"
  exit 2
fi

# Find all installed fast-uri instances
FOUND=0
VULN=0
while IFS= read -r pkg_json; do
  version=$(node -e "console.log(require('$pkg_json').version)" 2>/dev/null || echo "")
  if [ -z "$version" ]; then continue; fi
  FOUND=1
  # Affected: >= 4.1.3, < 4.1.5
  major=$(echo "$version" | cut -d. -f1)
  minor=$(echo "$version" | cut -d. -f2)
  patch=$(echo "$version" | cut -d. -f3 | cut -d- -f1)
  if [ "$major" -eq 4 ] && [ "$minor" -eq 1 ] && [ "$patch" -ge 3 ] && [ "$patch" -lt 5 ]; then
    echo "VULNERABLE — fast-uri $version found at $pkg_json"
    VULN=1
  else
    echo "PATCHED — fast-uri $version at $pkg_json (not in affected range 4.1.3–4.1.4)"
  fi
done < <(find "$PROJECT_DIR/node_modules" -path '*/fast-uri/package.json' -not -path '*/node_modules/*/node_modules/*' 2>/dev/null)

if [ "$FOUND" -eq 0 ]; then
  echo "PATCHED — fast-uri not found in $PROJECT_DIR (not a dependency)"
  exit 0
fi

if [ "$VULN" -eq 1 ]; then
  exit 1
else
  exit 0
fi
07 · Bottom Line

If you remember one thing.

TL;DR
This is a LOW finding. There is no noisgate mitigation SLA for LOW — treat it as backlog hygiene. Roll the upgrade to fast-uri ≥ 4.1.5 into your next scheduled dependency refresh under the noisgate remediation SLA (no hard deadline, backlog queue). Before even doing that, spend five minutes grepping your codebase for mailto URI parsing via fast-uri; if you find none — and you almost certainly won't — document the rationale and move on. The only teams who should care urgently are those with a confirmed parse→decide→reserialize→send pattern on untrusted mailto URIs, and even then the impact ceiling is email content manipulation, not compromise. Do not let this CVE displace real work on your patch queue.

Sources

  1. GHSA-jvvf-x445-j334 — GitHub Security Advisory
  2. fast-uri v4.1.5 release notes
  3. fast-uri GitHub repository
  4. fast-uri Security Advisories overview
  5. fast-uri on npm
  6. CISA Vulnerability Bulletin — Week of June 29, 2026
  7. Snyk — fast-uri vulnerabilities
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.