CVE-2026-90982
Executive Summary
CVE-2026-90982 is a case-sensitivity authorization bypass in @fastify/static, a Fastify plugin used to serve static files from a configured root directory. On case-insensitive filesystems (Windows and the default macOS volume), an unauthenticated remote attacker can read protected files by altering the letter case of a path segment, because the route matcher is case-sensitive while the underlying filesystem is not. The flaw affects all versions of @fastify/static before 10.1.4 and carries a CVSS score of 5.3 (Moderate), with low confidentiality impact and no integrity or availability impact.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability class is CWE-178 (Improper Handling of Case Sensitivity). It arises from a mismatch between two layers of path resolution:
- Application layer (case-sensitive): Fastify's route matcher and any configured route guard or
allowedPathrestriction evaluate the requested URL path using exact, case-sensitive string comparison. A guard configured to protect/admin/report.pdf, for example, matches only that exact casing. - Filesystem layer (case-insensitive): On Windows NTFS and the default macOS APFS/HFS+ volume,
/Admin/Report.PDF,/ADMIN/report.pdf, and/admin/report.pdfall resolve to the same file.
When an attacker requests a case-variant of a protected path, the case-sensitive route guard does not match, so the request falls through to the @fastify/static handler. The static handler then resolves the path — successfully, because the filesystem ignores case — and serves the protected file. The result is an unauthenticated read of a file that a route guard or allowedPath rule was explicitly configured to protect.
Critically, the description establishes clear boundaries that must not be overstated:
- The issue does not affect case-sensitive filesystems (e.g., standard Linux ext4). On those systems the case-variant request simply 404s.
- It is not a directory traversal. Nothing is served from outside the configured root. The bypass only reaches files inside the root that were intended to be gated by application-level authorization.
- The exposed asset is limited to files that reside within the static root and are nominally protected by a guard/
allowedPathrule.
The root cause is architectural: authorization decisions based on the raw request string are unsound when the enforcement point (Fastify routing) and the resource resolver (the OS filesystem) disagree on equality semantics. Version 10.1.4 fixes this by validating the requested path against its actual on-disk spelling and rejecting case-aliased paths before authorization is evaluated — moving the canonical comparison ahead of the guard check.
Exploitation Scenarios
No public proof-of-concept, exploit code, or Nuclei template is available for CVE-2026-90982. The attack chain below is inferred at the vulnerability-class level from the NVD description; no specific function names, endpoints, or file paths are fabricated.
Reconnaissance / target identification. The attacker identifies a Fastify application that uses
@fastify/staticto serve a root directory and that additionally implements route guards orallowedPathrules to protect specific files within that same root. Hosting on Windows or default macOS is a strong indicator the target is case-insensitive and therefore potentially vulnerable. Fingerprinting of the Fastify stack (e.g., default headers, error page behavior) supports target selection; port 3000 is the common Fastify default.Triggering the flaw class. The attacker enumerates or guesses a protected path (the guard or
allowedPathvalue). Rather than requesting it verbatim — which the guard would block or redirect — the attacker submits the same path with one or more path segments re-cased (for example, upper-casing a directory name). Because the route matcher compares case-sensitively, the guarded route is not selected; the request instead reaches the@fastify/statichandler.Payload / execution method (class level). The "payload" is simply the re-cased request path. There is no injection string, no traversal sequence, and no code execution. The static handler passes the path to the OS, which resolves the case-aliased name to the same protected file within the configured root, and the file content is returned in the HTTP response.
Post-exploitation impact. The attacker obtains the contents of a file that application logic intended to restrict. Because the bypass is unauthenticated (PR:N, UI:N), it can be automated and repeated across many candidate paths to harvest multiple protected files. The direct impact is confidentiality loss (C:L) only — no data modification (I:N) and no service disruption (A:N). The practical severity depends entirely on what the protected files contain (e.g., configuration, exports, or documents placed under the static root).
Impact Assessment
CVSS 3.1: 5.3 (Moderate) — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N.
- Attack Vector (N): exploitable remotely over the network.
- Attack Complexity (L): low — no special conditions beyond a case-insensitive filesystem and a case-sensitive guard/
allowedPathrule. - Privileges Required (N): none — the bypass is unauthenticated.
- User Interaction (N): none.
- Scope (U): the vulnerable component remains the security authority; the impact stays within the same authorization boundary.
- Confidentiality (L): limited — only files inside the configured static root that are nominally protected are reachable.
- Integrity (N) / Availability (N): no modification or disruption.
Blast radius. Any Fastify deployment using @fastify/static < 10.1.4 on Windows or default macOS volumes that relies on route guards or allowedPath rules to protect files within the static root. Linux deployments on case-sensitive filesystems are not affected. Because the exploit is unauthenticated and trivial to script, every exposed instance should be treated as potentially readable for any guarded static file. There is no evidence of in-the-wild exploitation (not in CISA KEV) and no known threat-actor campaign tied to this CVE.
Detection Guidance
Sigma Rule
title: Fastify Static Case-Aliased Path Access (CVE-2026-90982)
id: 3f9c1a72-8b4e-4d21-9a6e-fastify90982
status: experimental
description: Detects HTTP requests with mixed/odd letter-case path segments targeting Fastify static roots on case-insensitive filesystems, indicative of case-sensitivity authorization bypass.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-90982
author: valtersit.com Threat Intelligence
date: 2026/01/01
logsource:
category: webserver
product: fastify
detection:
selection_method:
cs-method:
- 'GET'
- 'HEAD'
selection_case:
cs-uri-stem|re: '/(?:[A-Z][a-z]+|[a-z]+[A-Z]|[A-Z]{2,})/'
filter_static_ext:
cs-uri-stem|endswith:
- '.pdf'
- '.json'
- '.csv'
- '.txt'
- '.html'
condition: selection_method and selection_case and filter_static_ext
fields:
- c-ip
- cs-uri-stem
- sc-status
falsepositives:
- Legitimate URLs with intended mixed case
level: medium
tags:
- attack.initial_access
- attack.t1190
- cve.2026.90982
YARA Rule
rule CVE_2026_90982_Fastify_Static_CaseBypass
{
meta:
description = "Detects case-aliased path handling patterns referencing @fastify/static vulnerable versions"
author = "valtersit.com Threat Intelligence"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-90982"
date = "2026-01-01"
cve = "CVE-2026-90982"
strings:
$pkg1 = "@fastify/static"
$ver1 = "10.1.0" ascii
$ver2 = "10.1.1" ascii
$ver3 = "10.1.2" ascii
$ver4 = "10.1.3" ascii
$opt1 = "allowedPath" ascii
$opt2 = "root:" ascii
condition:
$pkg1 and any of ($ver*) and any of ($opt*)
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-90982 Fastify Static Case-Sensitivity Authorization Bypass Attempt"; flow:established,to_server; http.method; content:"GET"; http.uri; pcre:"/\/(?:[A-Z][a-z]+|[a-z]+[A-Z])[A-Za-z0-9._-]*\//"; http.uri; content:".pdf"; nocase; http.header; content:"@fastify/static"; nocase; reference:cve,2026-90982; classtype:attempted-recon; sid:202690982; rev:1;)
Elastic Detection
sequence by source.ip with maxspan=30s
[ network where http.request.method in ("GET", "HEAD")
and http.request.uri regex~ "/[A-Z][a-z]+[A-Za-z0-9._-]*/" ]
[ network where http.request.method in ("GET", "HEAD")
and http.response.status_code == 200
and http.request.uri regex~ "\\.[A-Za-z]{2,4}$" ]
Splunk SPL Query
index=web sourcetype=fastify_access OR sourcetype=access_combined
| eval uri=coalesce(uri, uri_path, cs_uri_stem)
| where match(uri, "\/[A-Z][a-z]+[A-Za-z0-9._-]*\/")
| rex field=uri "(?<guardedpath>\/[A-Za-z0-9._\/-]+)$"
| stats count min(_time) as first_seen max(_time) as last_seen values(status) as status_codes by src_ip guardedpath
| where status_codes like "%200%"
| sort - count
Wazuh OSSEC Rule
<group name="fastify,cve-2026-90982,">
<rule id="202690" level="8">
<if_sid>31100</if_sid>
<field name="url">\.(pdf|json|csv|txt|html)$</field>
<regex type="pcre2">/[A-Z][a-z]+[A-Za-z0-9._-]*/</regex>
<description>CVE-2026-90982: Possible Fastify static case-sensitivity authorization bypass request</description>
<mitre>
<id>T1190</id>
</mitre>
<group>web,attack,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source).
Immediate mitigations.
- Serve static files from a case-sensitive filesystem (e.g., Linux ext4), which neutralizes the bypass entirely.
- If remaining on a case-insensitive filesystem, ensure route guards and
allowedPathrules account for every letter-case variant of each protected path, as explicitly recommended in the description. - Relocate files that require authorization out of the static root so they are never reachable by
@fastify/static. - Apply reverse-proxy or WAF rules that reject or normalize anomalous mixed-case path segments before they reach Fastify.
Patch / upgrade steps.
- The upstream fix is
@fastify/static10.1.4, which validates the requested path against its actual on-disk spelling and rejects case-aliased paths before authorization. Note: no patch evidence is currently available from tracked sources (0/4 confidence); confirm the fixed version from the authoritative advisory before deployment. - Stop the service, update the dependency to 10.1.4 (or later), reinstall, and restart.
- Verify the installed version and re-test guarded paths with mixed-case variants.
- The upstream fix is
Long-term hardening.
- Make authorization decisions on the canonical, OS-resolved path rather than the raw request string — never gate resources on case-sensitive string equality when the resolver is case-insensitive.
- Normalize and canonicalize all request paths at the edge (lowercase, resolve aliases) before routing.
- Inventory every application that uses
@fastify/staticand confirm filesystem case-sensitivity per environment (dev/QA/prod), since behavior differs between Linux and Windows/macOS. - Add detection content (above) to catch re-cased requests against guarded static paths.
References
- NVD — CVE-2026-90982: https://nvd.nist.gov/vuln/detail/CVE-2026-90982
@fastify/staticproject (npm): https://www.npmjs.com/package/@fastify/static- Fastify documentation — static file serving: https://fastify.dev/docs/latest/Reference/Plugins/static/
- CWE-178 — Improper Handling of Case Sensitivity: https://cwe.mitre.org/data/definitions/178.html
- CISA Known Exploited Vulnerabilities Catalog (CVE-2026-90982 not listed): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
No threat actor campaigns, exploit-in-the-wild evidence, public PoC, Nuclei template, or exploit code are known for this CVE at the time of writing. EPSS has not yet been scored by FIRST.org.