Skip to content

Commit

Permalink
feat: server.fs.deny support (vitejs#5378)
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Oct 27, 2021
1 parent d5e51f4 commit 1a15460
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 6 deletions.
9 changes: 9 additions & 0 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
8 changes: 8 additions & 0 deletions packages/playground/fs-serve/__tests__/fs-serve.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/fs-serve/root/src/.env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
KEY=safe
KEY=unsafe
18 changes: 15 additions & 3 deletions packages/playground/fs-serve/root/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ <h2>Unsafe /@fs/ Fetch</h2>
<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'
Expand All @@ -31,7 +34,7 @@ <h2>Nested Entry</h2>
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()
Expand All @@ -41,7 +44,7 @@ <h2>Nested Entry</h2>
})

// outside of allowed dir, treated as unsafe
fetch('/.env')
fetch('/unsafe.txt')
.then((r) => {
text('.unsafe-fetch-status', r.status)
return r.text()
Expand Down Expand Up @@ -76,7 +79,16 @@ <h2>Nested Entry</h2>
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 change: 1 addition & 0 deletions packages/playground/fs-serve/root/src/safe.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
KEY=safe
File renamed without changes.
16 changes: 15 additions & 1 deletion packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
}

/**
Expand Down Expand Up @@ -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)]
Expand All @@ -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
}
6 changes: 6 additions & 0 deletions packages/vite/src/node/server/middlewares/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
slash,
isFileReadable
} from '../../utils'
import match from 'minimatch'

const sirvOptions: Options = {
dev: true,
Expand Down Expand Up @@ -130,6 +131,8 @@ export function serveRawFsMiddleware(
}
}

const _matchOptions = { matchBase: true }

export function isFileServingAllowed(
url: string,
server: ViteDevServer
Expand All @@ -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 + '/')))
Expand Down
6 changes: 5 additions & 1 deletion packages/vite/types/shims.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down

0 comments on commit 1a15460

Please sign in to comment.