CVE-2024-23331
Executive Summary
CVE-2024-23331 is a path traversal vulnerability in the Vite development server that allows bypassing the server.fs.deny access control list on case-insensitive file systems (primarily Windows). By requesting files with case-augmented names (e.g., /..\\..\\..\\..\\..\\windows\\win.ini), an attacker can read sensitive files that should be blocked. The vulnerability arises because picomatch (the glob matching library used by Vite) defaults to case-sensitive matching, while the underlying file system does not discriminate case. This discrepancy allows an attacker to craft requests that bypass the deny list.
The vulnerability is rated CVSS 7.5 (High) with a vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N, indicating network-based exploitation with low complexity and no privileges required, leading to high confidentiality 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
Supply Chain & Package Security
Vite is a widely used frontend build tool and development server for JavaScript/TypeScript projects. It is distributed via npm. This vulnerability affects the development server component, which is typically run locally but can be exposed to a network. The supply chain risk is moderate: if a developer runs a Vite dev server on a shared network or exposes it inadvertently, an attacker can read arbitrary files from the host filesystem. The package itself is not compromised, but the default configuration of the dev server's file access controls is flawed on case-insensitive systems.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – The vulnerability can be exploited remotely over a network.
- Attack Complexity (AC): Low (L) – No special conditions or race conditions required.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) – Sensitive files (e.g., configuration, credentials) can be read.
- Integrity (I): None (N) – No file modification possible.
- Availability (A): None (N) – No denial of service.
Threat Level: High. The vulnerability is trivial to exploit (simple HTTP request with path traversal) and can lead to exposure of sensitive data such as environment variables, source code, or system files.
Deep Dive & Mechanics
The Vite dev server implements a file access control mechanism via the server.fs.deny configuration option. This option accepts an array of glob patterns (e.g., ['.env', '.git/**']) that define which files should be blocked from direct HTTP access. The blocking is enforced by a middleware that checks incoming requests against these patterns using the picomatch library.
The Flaw: picomatch performs case-sensitive glob matching by default. On case-insensitive file systems (Windows, macOS by default), the operating system treats FILE.TXT and file.txt as the same file. However, picomatch will see FILE.TXT as a different pattern than file.txt. Therefore, if the deny list contains file.txt, a request for FILE.TXT will not match the deny pattern, and the file will be served.
Bypass Technique: An attacker can request a file using a case-augmented version of its name. For example, to bypass a deny rule for .env, the attacker requests /.Env or /.ENV. The file system resolves this to the actual .env file, but the glob matcher does not flag it.
Attack Surface: The vulnerability is limited to case-insensitive file systems. Windows is the primary target. macOS is also case-insensitive by default but less commonly used for development servers exposed to networks.
Comparison to CVE-2023-34092: This CVE is a variant of CVE-2023-34092, which was a similar bypass using URL encoding. The current CVE reduces the surface area to case-insensitive systems only.
Vulnerable vs. Patched Code
Vulnerable Code (Vite < 5.0.12):
The middleware that checks file access uses picomatch directly without normalizing the case of the requested path.
// Simplified vulnerable logic
import { picomatch } from 'picomatch'
const denyPatterns = config.server.fs.deny.map(pattern => picomatch(pattern))
app.use((req, res, next) => {
const filePath = decodeURI(req.url)
for (const matcher of denyPatterns) {
if (matcher(filePath)) {
return res.status(403).send('Access denied')
}
}
// serve file
})
Patched Code (Vite >= 5.0.12): The fix normalizes the requested file path to lowercase before matching against the deny patterns. This ensures that case variations are caught.
// Simplified patched logic
import { picomatch } from 'picomatch'
const denyPatterns = config.server.fs.deny.map(pattern => picomatch(pattern, { nocase: true }))
app.use((req, res, next) => {
const filePath = decodeURI(req.url).toLowerCase() // Normalize to lowercase
for (const matcher of denyPatterns) {
if (matcher(filePath)) {
return res.status(403).send('Access denied')
}
}
// serve file
})
The key changes:
- The
picomatchpatterns are created with the{ nocase: true }option to make them case-insensitive. - The requested file path is converted to lowercase before matching.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A Vite dev server running on a case-insensitive file system (Windows).
- The dev server is accessible over the network (e.g., bound to
0.0.0.0or exposed via a reverse proxy). - The
server.fs.denyoption is configured to block sensitive files (default or custom).
Exploit Steps:
- Identify the Vite dev server endpoint (e.g.,
http://target:5173). - Attempt to read a sensitive file using case variation. For example, to read the
.envfile:
Or using path traversal:GET /@fs/C:/Users/Admin/project/.Env HTTP/1.1 Host: target:5173
(Note: On Windows, backslashes are used in paths, but HTTP requests typically use forward slashes. The Vite dev server may normalize them.)GET /@fs/..\..\..\..\..\windows\win.ini HTTP/1.1 - If the deny list blocks
.envbut not.Env, the file will be served.
Proof-of-Concept (Python):
import requests
target = "http://target:5173"
# Attempt to read .env file using case variation
payload = "/@fs/C:/Users/Admin/project/.Env"
response = requests.get(target + payload)
print(response.text)
Blue Team (Detection & Hardening)
Detection:
- Monitor HTTP access logs for requests containing
@fswith unusual casing (e.g.,.Env,.ENV,Win.Ini). - Look for path traversal patterns like
..\\or../in the URL. - Alert on requests to sensitive file extensions (
.env,.git/config,web.config, etc.) from the Vite dev server.
Hardening:
- Upgrade Vite to the latest patched version (5.0.12+).
- If upgrade is not possible, restrict network access to the dev server (e.g., bind to
127.0.0.1only, use firewall rules). - Implement a reverse proxy (e.g., Nginx) with additional access controls.
- Use a case-insensitive file system for development (Windows default) but ensure the dev server is not exposed to untrusted networks.
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP requests to Vite dev server with paths containing
@fsand mixed-case file names (e.g.,.Env,Win.Ini). - Requests with path traversal sequences (
..\\,../) targeting system files. - Unusual HTTP 200 responses for files that should be blocked (e.g.,
.env,package.json).
- HTTP requests to Vite dev server with paths containing
File System IOCs:
- Access to sensitive files via the Vite dev server process (check process monitor logs).
- Unexpected reads of
.env,.git/config, or system files (e.g.,C:\Windows\win.ini).
Log IOCs:
- Vite dev server logs showing requests to paths with abnormal casing.
- Web server logs (if behind a proxy) showing similar patterns.
Detection Engineering
YARA Rule
rule CVE_2024_23331_Vite_Path_Traversal {
meta:
description = "Detects HTTP requests exploiting CVE-2024-23331 Vite path traversal via case variation"
author = "Valters IT"
date = "2024-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2024-23331"
severity = "high"
strings:
$s1 = "/@fs/" nocase
$s2 = "..\\" ascii
$s3 = "../" ascii
$s4 = ".env" nocase
$s5 = "win.ini" nocase
$s6 = "web.config" nocase
condition:
any of ($s*) and (
// Look for mixed-case patterns in the path
for any i in (1..#s1) : (
@s1[i] and (
// Check for case variation after /@fs/
uint16(@s1[i] + 5) != 0x2e65 and // not ".e" (lowercase)
uint16(@s1[i] + 5) != 0x2e45 // not ".E" (uppercase)
)
)
)
}
Sigma Rule
title: Vite Dev Server Path Traversal via Case Variation (CVE-2024-23331)
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP requests to Vite dev server that attempt to bypass file access controls using case variation.
author: Valters IT
date: 2024-01-01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-23331
logsource:
category: webserver
product: generic
detection:
selection:
cs-uri-query|contains:
- '/@fs/'
- '..\\'
- '../'
cs-uri-query|re: '(?i)\\.(env|git|config|ini|json|yaml|yml|xml|pem|key|crt|cer|pfx|p12|jks|keystore|truststore|properties|conf|cfg|log|txt|md|rst|html|htm|php|asp|aspx|jsp|do|action|pl|py|rb|sh|bat|cmd|ps1|vbs|js|ts|jsx|tsx|vue|svelte|css|scss|sass|less|styl|map|br|gz|zip|tar|tgz|bz2|7z|rar|dmg|iso|img|bin|exe|dll|so|dylib|sys|ini|cfg|conf|config|env|gitignore|gitattributes|editorconfig|eslintrc|prettierrc|babelrc|tsconfig|jsconfig|package-lock|yarn-lock|pnpm-lock|composer-lock|gemfile-lock|cargo-lock|go-sum|go-mod|nuget-config|pipfile|requirements|setup-cfg|makefile|dockerfile|docker-compose|k8s|yaml|yml|xml|json|toml|ini|cfg|conf|properties|env|secret|key|cert|pem|p12|pfx|jks|keystore|truststore|log|txt|md|rst|html|htm|php|asp|aspx|jsp|do|action|pl|py|rb|sh|bat|cmd|ps1|vbs|js|ts|jsx|tsx|vue|svelte|css|scss|sass|less|styl|map|br|gz|zip|tar|tgz|bz2|7z|rar|dmg|iso|img|bin|exe|dll|so|dylib|sys)$'
condition: selection
falsepositives:
- Legitimate use of case-insensitive file names in development
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-23331 Vite Dev Server Path Traversal via Case Variation"; flow:to_server,established; content:"/@fs/"; nocase; http_uri; pcre:"/(?i)\\.(env|git|config|ini|json|yaml|yml|xml|pem|key|crt|cer|pfx|p12|jks|keystore|truststore|properties|conf|cfg|log|txt|md|rst|html|htm|php|asp|aspx|jsp|do|action|pl|py|rb|sh|bat|cmd|ps1|vbs|js|ts|jsx|tsx|vue|svelte|css|scss|sass|less|styl|map|br|gz|zip|tar|tgz|bz2|7z|rar|dmg|iso|img|bin|exe|dll|so|dylib|sys)/Ri"; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Vite to the latest patched version:
npm install vite@5.0.12(or latest)- For older major versions:
vite@4.5.2,vite@3.2.8,vite@2.9.17
- Restrict network access to the Vite dev server:
- Bind to
127.0.0.1only (default in newer versions). - Use firewall rules to block external access to the dev server port.
- Bind to
- Review
server.fs.denyconfiguration and ensure it covers all sensitive files. Note that the patch makes the matching case-insensitive, so patterns should be lowercase.
Long-term Mitigations:
- Use a reverse proxy (e.g., Nginx, Caddy) with additional access controls.
- Implement a Web Application Firewall (WAF) rule to block path traversal attempts.
- Educate developers on the risks of exposing dev servers to networks.
- Consider using case-sensitive file systems for development (e.g., Linux, or enable case sensitivity on Windows via
fsutil.exe).
Workaround (if upgrade is not possible):
- Set
server.hostto'127.0.0.1'invite.config.jsto prevent external access. - Use a VPN or SSH tunnel to access the dev server remotely.
Valters IT