diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts index 8b41781ce..e7e260c97 100644 --- a/packages/vite/src/node/server/middlewares/static.ts +++ b/packages/vite/src/node/server/middlewares/static.ts @@ -259,7 +259,7 @@ export function isFileLoadingAllowed( return false } -function ensureServingAccess( +export function ensureServingAccess( url: string, server: ViteDevServer, res: ServerResponse, diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index c5e65ac2d..72e9e3e9b 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -12,6 +12,7 @@ import { isJSRequest, normalizePath, prettifyUrl, + rawRE, removeImportQuery, removeTimestampQuery, urlRE, @@ -34,6 +35,7 @@ import { import { ERR_CLOSED_SERVER } from '../pluginContainer' import { cleanUrl, unwrapId, withTrailingSlash } from '../../../shared/utils' import { NULL_BYTE_PLACEHOLDER } from '../../../shared/constants' +import { ensureServingAccess } from './static' const debugCache = createDebugger('vite:cache') @@ -164,6 +166,13 @@ export function transformMiddleware( warnAboutExplicitPublicPathInUrl(url) } + if ( + (rawRE.test(url) || urlRE.test(url)) && + !ensureServingAccess(url, server, res, next) + ) { + return + } + if ( isJSRequest(url) || isImportRequest(url) || diff --git a/playground/fs-serve/__tests__/fs-serve.spec.ts b/playground/fs-serve/__tests__/fs-serve.spec.ts index 9d9d4c6ec..16ecc0b78 100644 --- a/playground/fs-serve/__tests__/fs-serve.spec.ts +++ b/playground/fs-serve/__tests__/fs-serve.spec.ts @@ -77,6 +77,11 @@ describe.runIf(isServe)('main', () => { expect(await page.textContent('.unsafe-fs-fetch-status')).toBe('403') }) + test('unsafe fs fetch', async () => { + expect(await page.textContent('.unsafe-fs-fetch-raw')).toBe('') + expect(await page.textContent('.unsafe-fs-fetch-raw-status')).toBe('403') + }) + test('unsafe fs fetch with special characters (#8498)', async () => { expect(await page.textContent('.unsafe-fs-fetch-8498')).toBe('') expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('404') diff --git a/playground/fs-serve/root/src/index.html b/playground/fs-serve/root/src/index.html index 06bee3f86..fb1276d79 100644 --- a/playground/fs-serve/root/src/index.html +++ b/playground/fs-serve/root/src/index.html @@ -35,6 +35,8 @@

Unsafe /@fs/ Fetch


 

+

+

 

 

 

@@ -188,6 +190,24 @@
       console.error(e)
     })
 
+  // not imported before, outside of root, treated as unsafe
+  fetch(
+    joinUrlSegments(
+      base,
+      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',
+    ),
+  )
+    .then((r) => {
+      text('.unsafe-fs-fetch-raw-status', r.status)
+      return r.json()
+    })
+    .then((data) => {
+      text('.unsafe-fs-fetch-raw', JSON.stringify(data))
+    })
+    .catch((e) => {
+      console.error(e)
+    })
+
   // outside root with special characters #8498
   fetch(
     joinUrlSegments(