diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index 8515c88db31a73..01f4937759fce5 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -12,10 +12,8 @@ import { isJSRequest, normalizePath, prettifyUrl, - rawRE, removeImportQuery, removeTimestampQuery, - urlRE, } from '../../utils' import { send } from '../send' import { ERR_LOAD_URL, transformRequest } from '../transformRequest' @@ -45,6 +43,11 @@ const debugCache = createDebugger('vite:cache') const knownIgnoreList = new Set(['/', '/favicon.ico']) const trailingQuerySeparatorsRE = /[?&]+$/ +// TODO: consolidate this regex pattern with the url, raw, and inline checks in plugins +const urlRE = /[?&]url\b/ +const rawRE = /[?&]raw\b/ +const inlineRE = /[?&]inline\b/ + /** * A middleware that short-circuits the middleware chain to serve cached transformed modules */ @@ -176,7 +179,8 @@ export function transformMiddleware( ) if ( (rawRE.test(urlWithoutTrailingQuerySeparators) || - urlRE.test(urlWithoutTrailingQuerySeparators)) && + urlRE.test(urlWithoutTrailingQuerySeparators) || + inlineRE.test(urlWithoutTrailingQuerySeparators)) && !ensureServingAccess( urlWithoutTrailingQuerySeparators, server, diff --git a/playground/fs-serve/__tests__/fs-serve.spec.ts b/playground/fs-serve/__tests__/fs-serve.spec.ts index 4f55df0faa3b42..795c70e5ae201a 100644 --- a/playground/fs-serve/__tests__/fs-serve.spec.ts +++ b/playground/fs-serve/__tests__/fs-serve.spec.ts @@ -67,6 +67,18 @@ describe.runIf(isServe)('main', () => { expect(await page.textContent('.unsafe-fetch-8498-2-status')).toBe('404') }) + test('unsafe fetch import inline', async () => { + expect(await page.textContent('.unsafe-fetch-import-inline-status')).toBe( + '403', + ) + }) + + test('unsafe fetch raw query import', async () => { + expect( + await page.textContent('.unsafe-fetch-raw-query-import-status'), + ).toBe('403') + }) + test('safe fs fetch', async () => { expect(await page.textContent('.safe-fs-fetch')).toBe(stringified) expect(await page.textContent('.safe-fs-fetch-status')).toBe('200') @@ -120,6 +132,18 @@ describe.runIf(isServe)('main', () => { expect(await page.textContent('.unsafe-fs-fetch-8498-2-status')).toBe('404') }) + test('unsafe fs fetch import inline', async () => { + expect( + await page.textContent('.unsafe-fs-fetch-import-inline-status'), + ).toBe('403') + }) + + test('unsafe fs fetch import inline wasm init', async () => { + expect( + await page.textContent('.unsafe-fs-fetch-import-inline-wasm-init-status'), + ).toBe('403') + }) + test('nested entry', async () => { expect(await page.textContent('.nested-entry')).toBe('foobar') }) diff --git a/playground/fs-serve/root/src/index.html b/playground/fs-serve/root/src/index.html index 26375949c217fe..931ac38d5e749e 100644 --- a/playground/fs-serve/root/src/index.html +++ b/playground/fs-serve/root/src/index.html @@ -23,6 +23,8 @@

Unsafe Fetch


 

 

+

+

 
 

Safe /@fs/ Fetch


@@ -45,6 +47,8 @@ 

Unsafe /@fs/ Fetch


 

 

+

+

 
 

Nested Entry


@@ -160,6 +164,24 @@ 

Denied

console.error(e) }) + // outside of allowed dir with import inline + fetch(joinUrlSegments(base, '/unsafe.txt?import&inline')) + .then((r) => { + text('.unsafe-fetch-import-inline-status', r.status) + }) + .catch((e) => { + console.error(e) + }) + + // outside of allowed dir with raw query import + fetch(joinUrlSegments(base, '/unsafe.txt?raw?import')) + .then((r) => { + text('.unsafe-fetch-raw-query-import-status', r.status) + }) + .catch((e) => { + console.error(e) + }) + // imported before, should be treated as safe fetch(joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/safe.json')) .then((r) => { @@ -247,6 +269,35 @@

Denied

console.error(e) }) + // outside of root inline + fetch( + joinUrlSegments( + base, + joinUrlSegments('/@fs/', ROOT) + '/root/unsafe.txt?import&inline', + ), + ) + .then((r) => { + text('.unsafe-fs-fetch-import-inline-status', r.status) + }) + .catch((e) => { + console.error(e) + }) + + // outside of root inline, faux wasm?init + fetch( + joinUrlSegments( + base, + joinUrlSegments('/@fs/', ROOT) + + '/root/unsafe.txt?import&?inline=1.wasm?init', + ), + ) + .then((r) => { + text('.unsafe-fs-fetch-import-inline-wasm-init-status', r.status) + }) + .catch((e) => { + console.error(e) + }) + // outside root with special characters #8498 fetch( joinUrlSegments(