mirror of
https://github.com/vitejs/vite.git
synced 2024-11-22 07:09:05 +00:00
feat: server.fs.deny
support (#5378)
This commit is contained in:
parent
d5e51f4840
commit
1a15460bf3
@ -593,6 +593,15 @@ createServer()
|
||||
})
|
||||
```
|
||||
|
||||
### server.fs.deny
|
||||
|
||||
- **Experimental**
|
||||
- **Type:** `string[]`
|
||||
|
||||
Blocklist for sensitive files being restricted to be served by Vite dev server.
|
||||
|
||||
Default to `['.env', '.env.*', '*.{pem,crt}']`.
|
||||
|
||||
### server.origin
|
||||
|
||||
- **Type:** `string`
|
||||
|
@ -41,6 +41,14 @@ describe('main', () => {
|
||||
test('nested entry', async () => {
|
||||
expect(await page.textContent('.nested-entry')).toBe('foobar')
|
||||
})
|
||||
|
||||
test('nested entry', async () => {
|
||||
expect(await page.textContent('.nested-entry')).toBe('foobar')
|
||||
})
|
||||
|
||||
test('denied', async () => {
|
||||
expect(await page.textContent('.unsafe-dotenv')).toBe('404')
|
||||
})
|
||||
} else {
|
||||
test('dummy test to make jest happy', async () => {
|
||||
// Your test suite must contain at least one test.
|
||||
|
@ -1 +1 @@
|
||||
KEY=safe
|
||||
KEY=unsafe
|
||||
|
@ -23,6 +23,9 @@
|
||||
<h2>Nested Entry</h2>
|
||||
<pre class="nested-entry"></pre>
|
||||
|
||||
<h2>Denied</h2>
|
||||
<pre class="unsafe-dotenv"></pre>
|
||||
|
||||
<script type="module">
|
||||
import '../../entry'
|
||||
import json, { msg } from '../../safe.json'
|
||||
@ -31,7 +34,7 @@
|
||||
text('.named', msg)
|
||||
|
||||
// inside allowed dir, safe fetch
|
||||
fetch('/src/.env')
|
||||
fetch('/src/safe.txt')
|
||||
.then((r) => {
|
||||
text('.safe-fetch-status', r.status)
|
||||
return r.text()
|
||||
@ -41,7 +44,7 @@
|
||||
})
|
||||
|
||||
// outside of allowed dir, treated as unsafe
|
||||
fetch('/.env')
|
||||
fetch('/unsafe.txt')
|
||||
.then((r) => {
|
||||
text('.unsafe-fetch-status', r.status)
|
||||
return r.text()
|
||||
@ -76,7 +79,16 @@
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
// .env, denied by default
|
||||
fetch('/@fs/' + ROOT + '/root/.env')
|
||||
.then((r) => {
|
||||
text('.unsafe-dotenv', r.status)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
})
|
||||
|
||||
function text(sel, text) {
|
||||
document.querySelector(sel).textContent = text
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
1
packages/playground/fs-serve/root/src/safe.txt
Normal file
1
packages/playground/fs-serve/root/src/safe.txt
Normal file
@ -0,0 +1 @@
|
||||
KEY=safe
|
@ -162,6 +162,18 @@ export interface FileSystemServeOptions {
|
||||
* @experimental
|
||||
*/
|
||||
allow?: string[]
|
||||
|
||||
/**
|
||||
* Restrict accessing files that matches the patterns.
|
||||
*
|
||||
* This will have higher priority than `allow`.
|
||||
* Glob patterns are supported.
|
||||
*
|
||||
* @default ['.env', '.env.*', '*.crt', '*.pem']
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
deny?: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
@ -690,6 +702,7 @@ export function resolveServerOptions(
|
||||
): ResolvedServerOptions {
|
||||
const server = raw || {}
|
||||
let allowDirs = server.fs?.allow
|
||||
const deny = server.fs?.deny || ['.env', '.env.*', '*.{crt,pem}']
|
||||
|
||||
if (!allowDirs) {
|
||||
allowDirs = [searchForWorkspaceRoot(root)]
|
||||
@ -706,7 +719,8 @@ export function resolveServerOptions(
|
||||
server.fs = {
|
||||
// TODO: make strict by default
|
||||
strict: server.fs?.strict,
|
||||
allow: allowDirs
|
||||
allow: allowDirs,
|
||||
deny
|
||||
}
|
||||
return server as ResolvedServerOptions
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
slash,
|
||||
isFileReadable
|
||||
} from '../../utils'
|
||||
import match from 'minimatch'
|
||||
|
||||
const sirvOptions: Options = {
|
||||
dev: true,
|
||||
@ -130,6 +131,8 @@ export function serveRawFsMiddleware(
|
||||
}
|
||||
}
|
||||
|
||||
const _matchOptions = { matchBase: true }
|
||||
|
||||
export function isFileServingAllowed(
|
||||
url: string,
|
||||
server: ViteDevServer
|
||||
@ -140,6 +143,9 @@ export function isFileServingAllowed(
|
||||
const cleanedUrl = cleanUrl(url)
|
||||
const file = ensureLeadingSlash(normalizePath(cleanedUrl))
|
||||
|
||||
if (server.config.server.fs.deny.some((i) => match(file, i, _matchOptions)))
|
||||
return false
|
||||
|
||||
if (server.moduleGraph.safeModulesPath.has(file)) return true
|
||||
|
||||
if (server.config.server.fs.allow.some((i) => file.startsWith(i + '/')))
|
||||
|
6
packages/vite/types/shims.d.ts
vendored
6
packages/vite/types/shims.d.ts
vendored
@ -96,7 +96,11 @@ declare module 'rollup-plugin-web-worker-loader' {
|
||||
}
|
||||
|
||||
declare module 'minimatch' {
|
||||
function match(path: string, pattern: string): boolean
|
||||
function match(
|
||||
path: string,
|
||||
pattern: string,
|
||||
options?: { matchBase?: boolean }
|
||||
): boolean
|
||||
export default match
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user