Skip to content

Commit 1114b5d

Browse files
authored
fix(dev): trim trailing slash before server.fs.deny check (#20968) (#20969)
1 parent f12697c commit 1114b5d

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,12 @@ export function isFileLoadingAllowed(
274274

275275
if (!fs.strict) return true
276276

277-
if (config.fsDenyGlob(filePath)) return false
277+
// NOTE: `fs.readFile('/foo.png/')` tries to load `'/foo.png'`
278+
// so we should check the path without trailing slash
279+
const filePathWithoutTrailingSlash = filePath.endsWith('/')
280+
? filePath.slice(0, -1)
281+
: filePath
282+
if (config.fsDenyGlob(filePathWithoutTrailingSlash)) return false
278283

279284
if (config.safeModulePaths.has(filePath)) return true
280285

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ import {
1313
import type { Page } from 'playwright-chromium'
1414
import WebSocket from 'ws'
1515
import testJSON from '../safe.json'
16-
import { browser, isServe, page, viteServer, viteTestUrl } from '~utils'
16+
import {
17+
browser,
18+
isServe,
19+
isWindows,
20+
page,
21+
viteServer,
22+
viteTestUrl,
23+
} from '~utils'
1724

1825
const __dirname = path.dirname(fileURLToPath(import.meta.url))
1926

@@ -493,6 +500,23 @@ describe.runIf(isServe)('invalid request', () => {
493500
expect(response).toContain('HTTP/1.1 403 Forbidden')
494501
})
495502

503+
test('should deny request to denied file when a request ends with \\', async () => {
504+
const response = await sendRawRequest(viteTestUrl, '/src/.env\\')
505+
expect(response).toContain(
506+
isWindows ? 'HTTP/1.1 403 Forbidden' : 'HTTP/1.1 404 Not Found',
507+
)
508+
})
509+
510+
test('should deny request to denied file when a request ends with \\ with /@fs/', async () => {
511+
const response = await sendRawRequest(
512+
viteTestUrl,
513+
path.posix.join('/@fs/', root, 'root/src/.env') + '\\',
514+
)
515+
expect(response).toContain(
516+
isWindows ? 'HTTP/1.1 403 Forbidden' : 'HTTP/1.1 404 Not Found',
517+
)
518+
})
519+
496520
test('should deny request with /@fs/ to denied file when a request has /.', async () => {
497521
const response = await sendRawRequest(
498522
viteTestUrl,

0 commit comments

Comments
 (0)