diff --git a/packages/playground/fs-serve/__tests__/fs-serve.spec.ts b/packages/playground/fs-serve/__tests__/fs-serve.spec.ts
index 77940b40b3aebd..699e6bc111b74b 100644
--- a/packages/playground/fs-serve/__tests__/fs-serve.spec.ts
+++ b/packages/playground/fs-serve/__tests__/fs-serve.spec.ts
@@ -44,6 +44,11 @@ describe('main', () => {
expect(await page.textContent('.unsafe-fetch-8498-status')).toBe('403')
})
+ test('unsafe fetch with special characters 2 (#8498)', async () => {
+ expect(await page.textContent('.unsafe-fetch-8498-2')).toMatch('')
+ expect(await page.textContent('.unsafe-fetch-8498-2-status')).toBe('404')
+ })
+
test('safe fs fetch', async () => {
expect(await page.textContent('.safe-fs-fetch')).toBe(stringified)
expect(await page.textContent('.safe-fs-fetch-status')).toBe('200')
@@ -66,6 +71,13 @@ describe('main', () => {
expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('403')
})
+ test('unsafe fs fetch with special characters 2 (#8498)', async () => {
+ expect(await page.textContent('.unsafe-fs-fetch-8498-2')).toBe('')
+ expect(await page.textContent('.unsafe-fs-fetch-8498-2-status')).toBe(
+ '404'
+ )
+ })
+
test('nested entry', async () => {
expect(await page.textContent('.nested-entry')).toBe('foobar')
})
diff --git a/packages/playground/fs-serve/root/src/index.html b/packages/playground/fs-serve/root/src/index.html
index 6939e0f4b09ed9..68eed69810c7d4 100644
--- a/packages/playground/fs-serve/root/src/index.html
+++ b/packages/playground/fs-serve/root/src/index.html
@@ -19,6 +19,8 @@
Unsafe Fetch
+
+
Safe /@fs/ Fetch
@@ -31,6 +33,8 @@ Unsafe /@fs/ Fetch
+
+
Nested Entry
@@ -100,6 +104,19 @@ Denied
console.error(e)
})
+ // outside of allowed dir with special characters 2 #8498
+ fetch('/src/%252e%252e%252funsafe%252etxt')
+ .then((r) => {
+ text('.unsafe-fetch-8498-2-status', r.status)
+ return r.text()
+ })
+ .then((data) => {
+ text('.unsafe-fetch-8498-2', data)
+ })
+ .catch((e) => {
+ console.error(e)
+ })
+
// imported before, should be treated as safe
fetch('/@fs/' + ROOT + '/safe.json')
.then((r) => {
@@ -133,6 +150,18 @@ Denied
text('.unsafe-fs-fetch-8498', JSON.stringify(data))
})
+ // outside root with special characters 2 #8498
+ fetch(
+ '/@fs/' + ROOT + '/root/src/%252e%252e%252f%252e%252e%252funsafe%252ejson'
+ )
+ .then((r) => {
+ text('.unsafe-fs-fetch-8498-2-status', r.status)
+ return r.json()
+ })
+ .then((data) => {
+ text('.unsafe-fs-fetch-8498-2', JSON.stringify(data))
+ })
+
// not imported before, inside root with special characters, treated as safe
fetch(
'/@fs/' +
diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts
index 659dfbae62ecfe..b30b1eeccea628 100644
--- a/packages/vite/src/node/server/middlewares/static.ts
+++ b/packages/vite/src/node/server/middlewares/static.ts
@@ -107,7 +107,7 @@ export function serveStaticMiddleware(
}
if (redirected) {
- req.url = redirected
+ req.url = encodeURIComponent(redirected)
}
serve(req, res, next)
@@ -142,7 +142,7 @@ export function serveRawFsMiddleware(
url = url.slice(FS_PREFIX.length)
if (isWindows) url = url.replace(/^[A-Z]:/i, '')
- req.url = url
+ req.url = encodeURIComponent(url)
serveFromRoot(req, res, next)
} else {
next()