Describe the bug
I am using colons in some paths for auto-generated files (using Laravel Wayfinder), which contain colons in route file names. These imports fail, because vite rejects any path with a colon in it.
Since #22572, isFileLoadingAllowed rejects any path that contains : while server.fs.strict is on. The check runs on every OS, but : is a valid character in file and folder names on Linux and macOS.
On 8.3.1 this breaks:
The server log also says the file is "outside of Vite serving allow list", then lists the folder that contains it.
Like I said, I ran into this with Laravel Wayfinder, which names route folders after route names, for example routes/company:logo/index.ts.
The ~ check from the same PR runs only on Windows, but the : check runs everywhere, which makes me think whether it was meant to cover NTFS volumes mounted on Linux or macOS?
I have a fix on a branch and I'd like to send a PR:
- Keep rejecting
: on Windows, where it can never be part of a file name.
- On other OS-es, allow
:, but also check the path with the stream part removed against server.fs.deny. So .env::$DATA is checked as .env and is still denied.
The trade-off: on an NTFS volume mounted on Linux or macOS, the streams of a file that is allowed and not denied become readable again, as they were before #22572. Would you accept that, or do you prefer a different approach?
I totally get it if you'd like to keep the behavior consistent across different OS-es, but I though this is at least worth a discussion?
Reproduction
https://github.com/ragulka/vite-colon-path-repro
Steps to reproduce
-
Clone the reproduction and start the dev server:
git clone https://github.com/ragulka/vite-colon-path-repro.git
cd vite-colon-path-repro
pnpm install
pnpm dev
-
Open http://localhost:5173.
Expected: loaded: route:name
Actual: failed: Failed to fetch dynamically imported module: http://localhost:5173/src/route:name/index.js
Requesting the file directly gives the same result:
curl -i http://localhost:5173/src/route:name/index.js
# HTTP/1.1 403 Forbidden
-
To see the folder case, clone the same repo into a folder with : in its name:
git clone https://github.com/ragulka/vite-colon-path-repro.git 'my:app'
cd 'my:app'
pnpm install
pnpm dev
Open http://localhost:5173. Every file returns 403, including index.html, so the page doesn't load.
System Info
System:
OS: macOS 27.0.1
CPU: (10) arm64 Apple M1 Max
Memory: 366.94 MB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.22.2 - /Users/ragulka/.nvm/versions/node/v22.22.2/bin/node
npm: 10.9.7 - /Users/ragulka/.nvm/versions/node/v22.22.2/bin/npm
pnpm: 10.33.4 - /Users/ragulka/.nvm/versions/node/v22.22.2/bin/pnpm
Deno: 2.7.1 - /opt/homebrew/bin/deno
Browsers:
Brave Browser: 153.1.95.101
Chrome: 154.0.8037.92
Firefox: 123.0.1
Firefox Developer Edition: 153.0
Safari: 27.0.1
npmPackages:
@vitejs/plugin-vue: ^6.0.8 => 6.0.8
vite: ^8.2.1 => 8.2.1
Used Package Manager
pnpm
Logs
No response
Validations
Describe the bug
I am using colons in some paths for auto-generated files (using Laravel Wayfinder), which contain colons in route file names. These imports fail, because vite rejects any path with a colon in it.
Since #22572, isFileLoadingAllowed rejects any path that contains
:whileserver.fs.strictis on. The check runs on every OS, but:is a valid character in file and folder names on Linux and macOS.On 8.3.1 this breaks:
import('./route:name/index.js')gets a 403. Static imports still work, but only because import analysis pre-transforms them withwarmupRequest, which skips the check.:in its name. Every file returns 403, including index.html.The server log also says the file is "outside of Vite serving allow list", then lists the folder that contains it.
Like I said, I ran into this with Laravel Wayfinder, which names route folders after route names, for example
routes/company:logo/index.ts.The
~check from the same PR runs only on Windows, but the:check runs everywhere, which makes me think whether it was meant to cover NTFS volumes mounted on Linux or macOS?I have a fix on a branch and I'd like to send a PR:
:on Windows, where it can never be part of a file name.:, but also check the path with the stream part removed againstserver.fs.deny. So.env::$DATAis checked as.envand is still denied.The trade-off: on an NTFS volume mounted on Linux or macOS, the streams of a file that is allowed and not denied become readable again, as they were before #22572. Would you accept that, or do you prefer a different approach?
I totally get it if you'd like to keep the behavior consistent across different OS-es, but I though this is at least worth a discussion?
Reproduction
https://github.com/ragulka/vite-colon-path-repro
Steps to reproduce
Clone the reproduction and start the dev server:
git clone https://github.com/ragulka/vite-colon-path-repro.git cd vite-colon-path-repro pnpm install pnpm devOpen http://localhost:5173.
Expected:
loaded: route:nameActual:
failed: Failed to fetch dynamically imported module: http://localhost:5173/src/route:name/index.jsRequesting the file directly gives the same result:
curl -i http://localhost:5173/src/route:name/index.js # HTTP/1.1 403 ForbiddenTo see the folder case, clone the same repo into a folder with
:in its name:Open http://localhost:5173. Every file returns 403, including
index.html, so the page doesn't load.System Info
System: OS: macOS 27.0.1 CPU: (10) arm64 Apple M1 Max Memory: 366.94 MB / 64.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 22.22.2 - /Users/ragulka/.nvm/versions/node/v22.22.2/bin/node npm: 10.9.7 - /Users/ragulka/.nvm/versions/node/v22.22.2/bin/npm pnpm: 10.33.4 - /Users/ragulka/.nvm/versions/node/v22.22.2/bin/pnpm Deno: 2.7.1 - /opt/homebrew/bin/deno Browsers: Brave Browser: 153.1.95.101 Chrome: 154.0.8037.92 Firefox: 123.0.1 Firefox Developer Edition: 153.0 Safari: 27.0.1 npmPackages: @vitejs/plugin-vue: ^6.0.8 => 6.0.8 vite: ^8.2.1 => 8.2.1Used Package Manager
pnpm
Logs
No response
Validations