Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions packages/vite/src/node/server/middlewares/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -176,7 +179,8 @@ export function transformMiddleware(
)
if (
(rawRE.test(urlWithoutTrailingQuerySeparators) ||
urlRE.test(urlWithoutTrailingQuerySeparators)) &&
urlRE.test(urlWithoutTrailingQuerySeparators) ||
inlineRE.test(urlWithoutTrailingQuerySeparators)) &&
!ensureServingAccess(
urlWithoutTrailingQuerySeparators,
server,
Expand Down
24 changes: 24 additions & 0 deletions playground/fs-serve/__tests__/fs-serve.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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')
})
Expand Down
51 changes: 51 additions & 0 deletions playground/fs-serve/root/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ <h2>Unsafe Fetch</h2>
<pre class="unsafe-fetch-8498"></pre>
<pre class="unsafe-fetch-8498-2-status"></pre>
<pre class="unsafe-fetch-8498-2"></pre>
<pre class="unsafe-fetch-import-inline-status"></pre>
<pre class="unsafe-fetch-raw-query-import-status"></pre>

<h2>Safe /@fs/ Fetch</h2>
<pre class="safe-fs-fetch-status"></pre>
Expand All @@ -45,6 +47,8 @@ <h2>Unsafe /@fs/ Fetch</h2>
<pre class="unsafe-fs-fetch-8498"></pre>
<pre class="unsafe-fs-fetch-8498-2-status"></pre>
<pre class="unsafe-fs-fetch-8498-2"></pre>
<pre class="unsafe-fs-fetch-import-inline-status"></pre>
<pre class="unsafe-fs-fetch-import-inline-wasm-init-status"></pre>

<h2>Nested Entry</h2>
<pre class="nested-entry"></pre>
Expand Down Expand Up @@ -160,6 +164,24 @@ <h2>Denied</h2>
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) => {
Expand Down Expand Up @@ -247,6 +269,35 @@ <h2>Denied</h2>
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(
Expand Down