CVE-2024-31207 (published 2024-04-04T16:15Z)

Vite (French word for "quick", pronounced /vit/, like "veet") is a frontend build tooling to improve the frontend development experience.`server.fs.deny` does not deny requests for patterns with directories. This vulnerability has been patched in version(s) 5.2.6, 5.1.7, 5.0.13, 4.5.3, 3.2.10 and 2.9.18.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/vitejs/vite
commit_details: repo_url: https://github.com/vitejs/vite
author: 翠 / green
author_date: 2024-03-24 21:31:50+09:00
msg: fix: `fs.deny` with globs with directories (#16250)
repository: repo_url: https://github.com/vitejs/vite
repo_name: vitejs/vite
description: Next generation frontend tooling. It's fast!
repo_language: TypeScript
owner: vitejs
file_changes: filename: index.ts
change_type: ModificationType.MODIFY
diff: @@ -685,10 +685,19 @@ export async function _createServer(
     _importGlobMap: new Map(),
     _forceOptimizeOnRestart: false,
     _pendingRequests: new Map(),
-    _fsDenyGlob: picomatch(config.server.fs.deny, {
-      matchBase: true,
-      nocase: true,
-    }),
+    _fsDenyGlob: picomatch(
+      // matchBase: true does not work as it's documented
+      // https://github.com/micromatch/picomatch/issues/89
+      // convert patterns without `/` on our side for now
+      config.server.fs.deny.map((pattern) =>
+        pattern.includes('/') ? pattern : `**/${pattern}`,
+      ),
+      {
+        matchBase: false,
+        nocase: true,
+        dot: true,
+      },
+    ),
     _shortcutsOptions: undefined,
   }
 

programming_language: TypeScript
filename: fs-serve-deny.spec.ts
change_type: ModificationType.ADD
diff: @@ -0,0 +1,17 @@
+import { describe, expect, test } from 'vitest'
+import { isServe, page, viteTestUrl } from '~utils'
+
+describe.runIf(isServe)('main', () => {
+  test('**/deny/** should deny src/deny/deny.txt', async () => {
+    const res = await page.request.fetch(
+      new URL('/src/deny/deny.txt', viteTestUrl).href,
+    )
+    expect(res.status()).toBe(403)
+  })
+  test('**/deny/** should deny src/deny/.deny', async () => {
+    const res = await page.request.fetch(
+      new URL('/src/deny/.deny', viteTestUrl).href,
+    )
+    expect(res.status()).toBe(403)
+  })
+})

programming_language: TypeScript
filename: package.json
change_type: ModificationType.MODIFY
diff: @@ -10,6 +10,9 @@
     "preview": "vite preview root",
     "dev:base": "vite root --config ./root/vite.config-base.js",
     "build:base": "vite build root --config ./root/vite.config-base.js",
-    "preview:base": "vite preview root --config ./root/vite.config-base.js"
+    "preview:base": "vite preview root --config ./root/vite.config-base.js",
+    "dev:deny": "vite root --config ./root/vite.config-deny.js",
+    "build:deny": "vite build root --config ./root/vite.config-deny.js",
+    "preview:deny": "vite preview root --config ./root/vite.config-deny.js"
   }
 }

programming_language: CoffeeScript
filename: .deny
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+.deny

programming_language: SQL
filename: deny.txt
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+deny

programming_language: SQL
filename: vite.config-deny.js
change_type: ModificationType.ADD
diff: @@ -0,0 +1,22 @@
+import path from 'node:path'
+import { defineConfig } from 'vite'
+
+export default defineConfig({
+  build: {
+    rollupOptions: {
+      input: {
+        main: path.resolve(__dirname, 'src/index.html'),
+      },
+    },
+  },
+  server: {
+    fs: {
+      strict: true,
+      allow: [path.resolve(__dirname, 'src')],
+      deny: ['**/deny/**'],
+    },
+  },
+  define: {
+    ROOT: JSON.stringify(path.dirname(__dirname).replace(/\\/g, '/')),
+  },
+})

programming_language: TypeScript