Skip to content

Commit f479cc5

Browse files
authored
fix(dev): trim trailing slash before server.fs.deny check (#20968)
1 parent 5adbc53 commit f479cc5

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
@@ -297,7 +297,12 @@ export function isFileLoadingAllowed(
297297

298298
if (!fs.strict) return true
299299

300-
if (config.fsDenyGlob(filePath)) return false
300+
// NOTE: `fs.readFile('/foo.png/')` tries to load `'/foo.png'`
301+
// so we should check the path without trailing slash
302+
const filePathWithoutTrailingSlash = filePath.endsWith('/')
303+
? filePath.slice(0, -1)
304+
: filePath
305+
if (config.fsDenyGlob(filePathWithoutTrailingSlash)) return false
301306

302307
if (config.safeModulePaths.has(filePath)) return true
303308

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

@@ -538,6 +545,23 @@ describe.runIf(isServe)('invalid request', () => {
538545
expect(response).toContain('HTTP/1.1 403 Forbidden')
539546
})
540547

548+
test('should deny request to denied file when a request ends with \\', async () => {
549+
const response = await sendRawRequest(viteTestUrl, '/src/.env\\')
550+
expect(response).toContain(
551+
isWindows ? 'HTTP/1.1 403 Forbidden' : 'HTTP/1.1 404 Not Found',
552+
)
553+
})
554+
555+
test('should deny request to denied file when a request ends with \\ with /@fs/', async () => {
556+
const response = await sendRawRequest(
557+
viteTestUrl,
558+
path.posix.join('/@fs/', root, 'root/src/.env') + '\\',
559+
)
560+
expect(response).toContain(
561+
isWindows ? 'HTTP/1.1 403 Forbidden' : 'HTTP/1.1 404 Not Found',
562+
)
563+
})
564+
541565
test('should deny request with /@fs/ to denied file when a request has /.', async () => {
542566
const response = await sendRawRequest(
543567
viteTestUrl,

0 commit comments

Comments
 (0)