Skip to content

Commit 26e1764

Browse files
authored
fix: backport #19761, fs check in transform middleware (#19763)
1 parent 86e7a6b commit 26e1764

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

packages/vite/src/node/server/middlewares/transform.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,18 @@ import {
3838
} from '../../plugins/optimizedDeps'
3939
import { ERR_CLOSED_SERVER } from '../pluginContainer'
4040
import { getDepsOptimizer } from '../../optimizer'
41-
import { rawRE, urlRE } from '../../plugins/asset'
4241
import { ensureServingAccess } from './static'
4342

4443
const debugCache = createDebugger('vite:cache')
4544

4645
const knownIgnoreList = new Set(['/', '/favicon.ico'])
4746
const trailingQuerySeparatorsRE = /[?&]+$/
4847

48+
// TODO: consolidate this regex pattern with the url, raw, and inline checks in plugins
49+
const urlRE = /[?&]url\b/
50+
const rawRE = /[?&]raw\b/
51+
const inlineRE = /[?&]inline\b/
52+
4953
export function transformMiddleware(
5054
server: ViteDevServer,
5155
): Connect.NextHandleFunction {
@@ -174,7 +178,8 @@ export function transformMiddleware(
174178
)
175179
if (
176180
(rawRE.test(urlWithoutTrailingQuerySeparators) ||
177-
urlRE.test(urlWithoutTrailingQuerySeparators)) &&
181+
urlRE.test(urlWithoutTrailingQuerySeparators) ||
182+
inlineRE.test(urlWithoutTrailingQuerySeparators)) &&
178183
!ensureServingAccess(
179184
urlWithoutTrailingQuerySeparators,
180185
server,

playground/fs-serve/__tests__/fs-serve.spec.ts

+24
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ describe.runIf(isServe)('main', () => {
6767
expect(await page.textContent('.unsafe-fetch-8498-2-status')).toBe('404')
6868
})
6969

70+
test('unsafe fetch import inline', async () => {
71+
expect(await page.textContent('.unsafe-fetch-import-inline-status')).toBe(
72+
'403',
73+
)
74+
})
75+
76+
test('unsafe fetch raw query import', async () => {
77+
expect(
78+
await page.textContent('.unsafe-fetch-raw-query-import-status'),
79+
).toBe('403')
80+
})
81+
7082
test('safe fs fetch', async () => {
7183
expect(await page.textContent('.safe-fs-fetch')).toBe(stringified)
7284
expect(await page.textContent('.safe-fs-fetch-status')).toBe('200')
@@ -120,6 +132,18 @@ describe.runIf(isServe)('main', () => {
120132
expect(await page.textContent('.unsafe-fs-fetch-8498-2-status')).toBe('404')
121133
})
122134

135+
test('unsafe fs fetch import inline', async () => {
136+
expect(
137+
await page.textContent('.unsafe-fs-fetch-import-inline-status'),
138+
).toBe('403')
139+
})
140+
141+
test('unsafe fs fetch import inline wasm init', async () => {
142+
expect(
143+
await page.textContent('.unsafe-fs-fetch-import-inline-wasm-init-status'),
144+
).toBe('403')
145+
})
146+
123147
test('nested entry', async () => {
124148
expect(await page.textContent('.nested-entry')).toBe('foobar')
125149
})

playground/fs-serve/root/src/index.html

+51
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ <h2>Unsafe Fetch</h2>
2323
<pre class="unsafe-fetch-8498"></pre>
2424
<pre class="unsafe-fetch-8498-2-status"></pre>
2525
<pre class="unsafe-fetch-8498-2"></pre>
26+
<pre class="unsafe-fetch-import-inline-status"></pre>
27+
<pre class="unsafe-fetch-raw-query-import-status"></pre>
2628

2729
<h2>Safe /@fs/ Fetch</h2>
2830
<pre class="safe-fs-fetch-status"></pre>
@@ -45,6 +47,8 @@ <h2>Unsafe /@fs/ Fetch</h2>
4547
<pre class="unsafe-fs-fetch-8498"></pre>
4648
<pre class="unsafe-fs-fetch-8498-2-status"></pre>
4749
<pre class="unsafe-fs-fetch-8498-2"></pre>
50+
<pre class="unsafe-fs-fetch-import-inline-status"></pre>
51+
<pre class="unsafe-fs-fetch-import-inline-wasm-init-status"></pre>
4852

4953
<h2>Nested Entry</h2>
5054
<pre class="nested-entry"></pre>
@@ -160,6 +164,24 @@ <h2>Denied</h2>
160164
console.error(e)
161165
})
162166

167+
// outside of allowed dir with import inline
168+
fetch(joinUrlSegments(base, '/unsafe.txt?import&inline'))
169+
.then((r) => {
170+
text('.unsafe-fetch-import-inline-status', r.status)
171+
})
172+
.catch((e) => {
173+
console.error(e)
174+
})
175+
176+
// outside of allowed dir with raw query import
177+
fetch(joinUrlSegments(base, '/unsafe.txt?raw?import'))
178+
.then((r) => {
179+
text('.unsafe-fetch-raw-query-import-status', r.status)
180+
})
181+
.catch((e) => {
182+
console.error(e)
183+
})
184+
163185
// imported before, should be treated as safe
164186
fetch(joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/safe.json'))
165187
.then((r) => {
@@ -247,6 +269,35 @@ <h2>Denied</h2>
247269
console.error(e)
248270
})
249271

272+
// outside of root inline
273+
fetch(
274+
joinUrlSegments(
275+
base,
276+
joinUrlSegments('/@fs/', ROOT) + '/root/unsafe.txt?import&inline',
277+
),
278+
)
279+
.then((r) => {
280+
text('.unsafe-fs-fetch-import-inline-status', r.status)
281+
})
282+
.catch((e) => {
283+
console.error(e)
284+
})
285+
286+
// outside of root inline, faux wasm?init
287+
fetch(
288+
joinUrlSegments(
289+
base,
290+
joinUrlSegments('/@fs/', ROOT) +
291+
'/root/unsafe.txt?import&?inline=1.wasm?init',
292+
),
293+
)
294+
.then((r) => {
295+
text('.unsafe-fs-fetch-import-inline-wasm-init-status', r.status)
296+
})
297+
.catch((e) => {
298+
console.error(e)
299+
})
300+
250301
// outside root with special characters #8498
251302
fetch(
252303
joinUrlSegments(

0 commit comments

Comments
 (0)