CVE-2026-15074: @fastify/static Route Guard Bypass via Dot-Dot Path Traversal
A flaw in @fastify/static lets attackers sneak dot-dot path segments past route-level authentication guards to read protected static files, without ever leaving the configured static root.

The problem
@fastify/static versions up to and including 10.1.0 do not reject .. or %2E%2E segments before resolving a file path. The router (find-my-way) does not normalize these segments during route matching, so a request like /foo/../deep/secret.txt hits the plugin's catch-all instead of the protected /deep/* route.
This is a bypass of the earlier fix for GHSA-x428-ghpx-8j92 (CVE-2026-6414). That fix only blocked encoded slashes (%2F). Dot-dot segments survive the decodeURI + encodeURI round-trip intact and are collapsed silently by @fastify/send's internal path.normalize, defeating any route-scoped middleware or guard that ran before the file is served.
The impact is limited to route-guard bypass within the configured static root. An attacker cannot escape the root directory using this bug alone, but they can read files under a path prefix that should have been blocked by middleware.
Proof of concept
A working proof-of-concept for CVE-2026-15074 in @fastify/static, with the exact payload below.
GET /public/../deep/secret.txt HTTP/1.1
Host: target.example.com
# Percent-encoded variant also works:
GET /public/%2E%2E/deep/secret.txt HTTP/1.1
Host: target.example.comThe getPathnameForSend helper (introduced to fix the prior %2F bypass) ran decodeURI then encodeURI on the incoming pathname. Both .. and %2E%2E survive that round-trip unchanged because they contain no characters that encodeURI encodes, so neither form was stripped.
Downstream, @fastify/send calls path.normalize on the pathname before its own traversal guard, which collapses foo/../deep into deep. By then, route-level guards have already run against the original un-normalized URL and did not match /deep/*, so access control is silently skipped.
The patch adds an explicit check in getPathnameForSend to detect and reject any pathname containing .. or %2E%2E segments before the path ever reaches @fastify/send, closing the gap that the previous fix left open. CWE-22 (Improper Limitation of a Pathname to a Restricted Directory).
The fix
Upgrade @fastify/static to version 10.1.1. If you cannot upgrade immediately, do not rely on Fastify route-based middleware or guards to protect files served by @fastify/static; move that logic into the static plugin's own allowedPath callback or a server-level hook that runs after normalization.
Reported by imssm99.
Related research
- highCVE-2026-55607CVE-2026-55607: @anthropic-ai/claude-code Sandbox Escape via Git Worktree Path Confusion
- high · 7.5PostCSS Path Traversal via sourceMappingURL Leads to Arbitrary .map File Disclosure
- high · 7.5CVE-2026-45623CVE-2026-45623: PostCSS Arbitrary File Read via sourceMappingURL Path Traversal
- highn8n Git Node fetch/pull/pushTags Operations Bypass Sandbox Path Restriction