← Back to Feed CACHED · 2026-11-02 10:53:08 · CACHE_KEY CVE-2026-120213
CVE-2026-120213 · CWE-22

@fastify/http-proxy prefix escape via decoded route parameter injection

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

A bouncer who checks your ID but forgets to re-encode it before writing your name on the guest list lets you add VIP room numbers to your wristband

@fastify/http-proxy 9.0.0 through 11.6.5 substitutes URL-decoded route parameters into rewritePrefix without re-encoding them. If an application pins clients to a fixed upstream path via parameterized prefix plus rewritePrefix, an attacker can send a route parameter containing encoded /, ?, or # so it decodes into real path separators and delimiters inside the upstream URI. This injects extra upstream path segments and strips the mandatory suffix the rewritePrefix was meant to enforce, without any dot-dot traversal. The result is an upstream path outside the intended prefix.

Vendor CRITICAL 9.1 is defensible for the vulnerable configuration: unauthenticated, low complexity, high confidentiality and integrity impact. But real-world severity is lower because this bug only manifests when the app uses parameterized prefix plus rewritePrefix to pin a fixed upstream path—a non-default pattern. Many installs are internal or use static prefixes, and the practical impact depends entirely on what the upstream exposes. We downgrade to HIGH, not because the bug is hard to exploit, but because the reachable vulnerable population is a subset of all deployments.

"URL-decoded route params become upstream path separators: prefix pinning is cosmetic."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Locate a Fastify app using parameterized prefix plus rewritePrefix

Find a public Fastify service that registers @fastify/http-proxy with a route like /proxy/:p and a rewritePrefix that pins :p into a fixed upstream path. Attackers can use Burp or manual curl to map routes and identify parameterized proxy endpoints.
Conditions required:
  • Public reachability to the Fastify app
  • App declares a parameterized prefix route
  • App sets rewritePrefix to substitute the route parameter into a fixed upstream path
Where this breaks in practice:
  • Most @fastify/http-proxy deployments use static prefixes or no rewritePrefix; this pinning pattern is only a subset.
  • Many Fastify apps sit behind an API gateway and are not directly reachable.
Detection/coverage: Not fingerprintable from the outside beyond standard Fastify headers; app-specific reconnaissance is required.
STEP 02

Send a route parameter with encoded separators and delimiters

Use curl --path-as-is or Burp Repeater to send a parameter value such as %2Fadmin%3Fstrip= or %2Finternal%23 to inject / and ?/# after URL decoding. The plugin decodes the parameter before substituting it into rewritePrefix, so the upstream URI gains real path separators and truncates the mandatory suffix.
Conditions required:
  • Attacker can control the parameterized prefix value
  • Upstream server interprets the decoded parameter as path rather than query or fragment
Where this breaks in practice:
  • Reverse proxies or WAFs that reject encoded slash sequences may block some payloads, but bypasses exist.
  • The app must not separately URL-encode or sanitize the route parameter; many apps do not because the plugin decodes internally.
Detection/coverage: WAF logs may show encoded path separators; most default rules do not flag because there is no ../ traversal.
STEP 03

Craft a valid upstream URI outside the intended prefix

The decoded parameter yields an upstream path outside the intended prefix boundary. The attacker does not need dot-dot; a fragment or query delimiter can truncate any fixed suffix and a slash adds segments, shifting the effective path. The upstream receives a route the rewritePrefix was never meant to expose.
Conditions required:
  • Upstream server trusts the decoded path after substitution
  • No additional path normalization on the upstream that would strip the injected segments
Where this breaks in practice:
  • Some upstream servers normalize paths differently; but many Node.js or nginx upstreams preserve the decoded path.
  • Application-specific routing may not have a sensitive destination, limiting impact.
Detection/coverage: Application access logs show unusual upstream request paths during exploitation.
STEP 04

Abuse the upstream misroute for SSRF or authorization bypass

With the path outside the intended prefix, the attacker can reach internal admin endpoints, health endpoints, metadata services, or other virtual hosts on the upstream. If the proxied service uses path-based authorization, the proxy now passes requests to privileged routes without the intended prefix check.
Conditions required:
  • Upstream has sensitive or privileged paths reachable via the proxy
  • Upstream does not independently enforce path-based authentication for the injected route
Where this breaks in practice:
  • If upstream is a static backend with no sensitive paths, impact is limited.
  • Network egress controls may limit SSRF to internal metadata endpoints.
Detection/coverage: SSRF may be detected by upstream access logs or EDR on the Fastify process making unusual internal requests.
STEP 05

Pivot through SSRF or stolen upstream access

If the upstream is an internal admin API, the attacker can dump data, manipulate state, or fetch cloud metadata. In authorization-bypass cases, the attacker may access tenant data outside their own segment, leading to data exposure or integrity violations.
Conditions required:
  • Upstream routes contain sensitive data or privileged actions
  • No second factor or IP allowlisting on the upstream
Where this breaks in practice:
  • Modern cloud metadata endpoints often require IMDSv2 tokens, adding friction.
  • Internal segmentation may block lateral movement from the proxy host.
Detection/coverage: Cloud metadata access attempts are alerted by AWS GuardDuty, Azure Defender, and equivalent controls.
03 · Compensating Control

1
HIGH 7.5→IGNORE 0.0
SEVERITY REDUCED
Upgrade @fastify/http-proxy to 11.6.6 or later — This is the permanent fix and removes the re-encoding bug. Apply within the noisgate mitigation SLA of 30 days if temporary controls are needed, and complete remediation within the noisgate remediation SLA of 180 days.
2
HIGH 7.5→MEDIUM 5.0
SEVERITY REDUCED
Block public access to vulnerable Fastify apps or enforce a WAF rule rejecting encoded path separators — If you cannot upgrade immediately, restrict the app to internal/authenticated networks or enforce a WAF rule denying %2f, %3f, and %23 in the parameterized prefix segment. This reduces unauthenticated remote reachability but may be bypassable.
3
HIGH 7.5→LOW 2.0
SEVERITY REDUCED
Remove or rewrite parameterized rewritePrefix routes — Rework Fastify routes to use static prefixes or re-encode route parameters before substitution. This neutralizes the vulnerable pattern without a package upgrade, though it may require application changes.
4
HIGH 7.5→HIGH 7.0
Monitor upstream logs for unexpected path traversal or encoded separator attempts — Enable strict upstream access logging and alert on unusual paths, encoded separators, or metadata endpoint calls. This does not prevent exploitation but speeds detection and containment.
What doesn't work
  • Blocking ../ sequences at WAF/IDS: this attack does not use dot-dot traversal.
  • URL-encoding route parameters at the application layer alone: the plugin decodes parameters before substitution, so app-level encoding may not survive unless done after plugin handling.
  • Relying on TLS or network segmentation alone: an attacker hitting the public Fastify endpoint still reaches the proxied upstream over the app's trusted channel.
04 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo known exploitation; not in CISA KEV as of this assessment.
Proof-of-concept availabilityTrivial to reproduce with curl --path-as-is or Burp Repeater once the vulnerable route is found; no dedicated public PoC repository required.
EPSS score / percentileNot present in FIRST EPSS as of assessment; no EPSS percentile available.
KEV statusNot listed in CISA Known Exploited Vulnerabilities.
CVSS vector interpretationCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N — network, low complexity, no privileges, no user interaction, high confidentiality and integrity impact, scope unchanged.
Affected versions9.0.0 through 11.6.5.
Fixed versions11.6.6.
Scanning / exposure dataNo Shodan/GreyNoise fingerprints for this application-level config; exposed Fastify apps are only visible if directly Internet-facing.
Disclosure date2026; exact date not supplied in the official record.
Reporting researcher/orgNot identified in the official record.

Sources.

  1. NVD CVE-2026-120213
  2. CVE.org record
  3. @fastify/http-proxy GitHub repository
  4. @fastify/http-proxy on npm
  5. CWE-22 Improper Limitation of a Pathname
  6. Fastify Plugins Reference
05 · The Call

Final Verdict
↓ DOWNGRADED to HIGH (7.5/10)

Why this verdict

  • Config prerequisite: Only applications using parameterized prefix plus rewritePrefix to pin a fixed upstream path are affected; this is a non-default subset of @fastify/http-proxy deployments.
  • Reachability friction: Many Fastify apps sit behind API gateways or are internal-only, reducing unauthenticated remote exposure.
  • Role multiplier: @fastify/http-proxy is an application-tier library, not a canonical high-value component (IdP, PAM, hypervisor, CA, edge appliance). Even as an SSRF primitive, the blast radius is limited to the upstream services the app already proxies; it does not directly yield domain, fleet, or supply-chain compromise in the typical installation.
  • Impact dependency: High confidentiality/integrity only if the upstream exposes sensitive or privileged paths. If upstream is a static or low-value service, impact drops materially.

Why not higher?

Not a default-exploit-everywhere bug: it requires a specific parameterized prefix plus rewritePrefix configuration and public reachability. The vendor CRITICAL 9.1 assumes every install has that pattern and a sensitive upstream, which overstates the real deployed population. No KEV or active exploitation evidence pushes back on top-end severity.

Why not lower?

When the vulnerable configuration is present, the exploit is unauthenticated, low complexity, and requires no dot-dot traversal, so common path-based detection misses it. The result can be upstream path restriction bypass, SSRF, or authorization bypass in the proxied service, with high confidentiality/integrity impact. There is no workaround other than upgrade.

06 · Verification

Crowdsourced verification payload.

Run this on the application host or CI runner inside the project directory. Requires Node.js and read access to package.json / node_modules. Invoke: bash check_cve_2026_120213.sh.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
set -euo pipefail

if command -v npm >/dev/null 2>&1; then
  version=$(npm list @fastify/http-proxy --depth=0 --parseable 2>/dev/null | awk -F '@' '/@fastify\/http-proxy@/{print $3; exit}')
elif [ -f node_modules/@fastify/http-proxy/package.json ]; then
  version=$(node -p "require('./node_modules/@fastify/http-proxy/package.json').version")
else
  echo "UNKNOWN"
  exit 2
fi

if [ -z "$version" ]; then
  echo "UNKNOWN"
  exit 2
fi

node -e '
const v = process.argv[1];
const parts = v.split("-")[0].split(".").map(Number);
let status = "PATCHED";
let code = 0;
if (parts[0] < 9) {
  status = "PATCHED"; code = 0;
} else if (parts[0] > 11 || (parts[0] === 11 && parts[1] > 6) || (parts[0] === 11 && parts[1] === 6 && parts[2] >= 6)) {
  status = "PATCHED"; code = 0;
} else {
  status = "VULNERABLE"; code = 1;
}
console.log(status);
process.exit(code);
' "$version"