Skip to content
Renesoft
About Products Services Robotics Cybersecurity Careers Contact
EN SV

Security Advisories

CVE-2026-90982

@fastify/static — Route-guard bypass via path case-folding

Medium 5.3 CWE-178 CWE-284 JavaScript · npm
5.3/10MediumCVSS 3.1 base score
LowMediumHighCritical
04.07.09.010
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N

Summary

@fastify/static serves files from a configured root directory. On a case-insensitive filesystem, a route guard or allowedPath restriction can be bypassed by changing the letter case of a path segment.

Technical analysis

The guard compares the request path case-sensitively, but the underlying filesystem on Windows and the default macOS volume resolves paths case-insensitively. A request for a path that differs only in case from a blocked one misses the guarded route, falls through to the static handler, and opens the same file. It is a case-insensitive-filesystem variant of the earlier CVE-2026-18427.

The 10.1.3 canonicalizer ignores case. isNonCanonicalPathname rejects \ and any path that posix.normalize would rewrite. /DEEP/secret.txt is already “normalized”, so it is treated as canonical and allowed through. @fastify/static 10.1.3 — isNonCanonicalPathname

The router is case-sensitive; the disk is not. A prefix hook on /deep/* never sees /DEEP/secret.txt. The static /* handler does. On Windows / default macOS, that request opens the same inode as /deep/secret.txt. find-my-way route match vs @fastify/send

The library already owns this quirk for \. The same helper rejects backslash because send treats it as a separator on Windows. Letter-case is the other Windows/macOS filesystem alias in the same function, left unhandled. That is why this is a library fix, not “the OS did it.” CVE-2026-18427 residual — case axis

10.1.3 — case-blind canonical check
function isNonCanonicalPathname(p) {
  if (p.includes('\\')) return true   // Windows separator — they did fix this
  return path.posix.normalize(p) !== p     // '/DEEP/secret.txt' === itself → allowed
}

// find-my-way:  /DEEP/*  does not match  /deep/*  (case-sensitive)
// send + NTFS/APFS: DEEP/secret.txt  opens  deep/secret.txt

Proof of concept

Renesoft confirmed this against the real package in an isolated environment, with no live systems. The attack path, then the recorded test output:

  1. App mounts static files and a prefix guard — a hook on /deep/*, or an allowedPath predicate that denies /secret/.
  2. Request the same path with a different letter case — GET /DEEP/secret.txt or GET /files/SECRET/data.txt. Encoded dots, extra slashes, and %2F stay blocked by the earlier CVEs.
  3. The guard never runs; the file is served — response body hashes equal the on-disk guarded file. Changing only the filename case under a still-matching prefix (/deep/Secret.txt) does not bypass — the guarded segment itself has to fold.
poc.js — real 10.1.3 · win32
$ node poc/poc.js

GET /deep/secret.txt              401  guard runs
GET /x/../deep/secret.txt         403  CVE-2026-15074 still on
GET //deep/secret.txt             403  CVE-2026-18427 still on
GET /DEEP/secret.txt              200  serves guarded file  (sha256 match)

GET /files/secret/data.txt        404  allowedPath denies
GET /files/SECRET/data.txt        200  serves denied file  (sha256 match)

Impact

On case-insensitive hosts, an attacker reaches files that a path restriction was meant to block.

Affected versions

Affected
< 10.1.4
Fixed
10.1.4
CVSS
5.3 (3.1)
Weakness
CWE-178 · CWE-284
Ecosystem
JavaScript · npm
Disclosed
2026-09-17

Remediation

Fixed in 10.1.4. Applications below that version should upgrade.

Timeline

  • 2026-09-12Found and reproduced on 10.1.3 as a residual of CVE-2026-18427 on the case axis.
  • 2026-09-12Reported privately through GitHub private vulnerability reporting.
  • 2026-09-17Published; fixed in 10.1.4 and CVE-2026-90982 assigned.

References

  • GHSA-r799-r9gc-m956
  • CVE-2026-90982
  • npm: @fastify/static
  • Source

← All advisories

Renesoft

Conviction, compiled.

© 2026 Renesoft ABReg. no. 559593-4489Malmö, SwedenCareersCybersecurityPrivacy policy
v7.4.2 · cbb0edd