VYPR
Medium severity5.9NVD Advisory· Published Apr 4, 2024· Updated Apr 15, 2026

CVE-2024-31207

CVE-2024-31207

Description

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.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
vitenpm
>= 2.7.0, < 2.9.182.9.18
vitenpm
>= 3.0.0, < 3.2.103.2.10
vitenpm
>= 4.0.0, < 4.5.34.5.3
vitenpm
>= 5.0.0, < 5.0.135.0.13
vitenpm
>= 5.1.0, < 5.1.75.1.7
vitenpm
>= 5.2.0, < 5.2.65.2.6

Patches

6
011bbca350e4

fix: port #16250 to v2 (#16254)

https://github.com/vitejs/vite翠 / greenMar 24, 2024via ghsa
7 files changed · +53 4
  • packages/playground/fs-serve/package.json+4 1 modified
    @@ -6,6 +6,9 @@
         "dev": "vite root",
         "build": "vite build root",
         "debug": "node --inspect-brk ../../vite/bin/vite",
    -    "preview": "vite preview"
    +    "preview": "vite preview",
    +    "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"
       }
     }
    
  • packages/playground/fs-serve/root/src/deny/.deny+1 0 added
    @@ -0,0 +1 @@
    +.deny
    
  • packages/playground/fs-serve/root/src/deny/deny.txt+1 0 added
    @@ -0,0 +1 @@
    +deny
    
  • packages/playground/fs-serve/root/vite.config-deny.js+15 0 added
    @@ -0,0 +1,15 @@
    +const path = require('path')
    +const { defineConfig } = require('vite')
    +
    +module.exports = defineConfig({
    +  server: {
    +    fs: {
    +      strict: true,
    +      allow: [path.resolve(__dirname, 'src')],
    +      deny: ['**/deny/**']
    +    }
    +  },
    +  define: {
    +    ROOT: JSON.stringify(path.dirname(__dirname).replace(/\\/g, '/'))
    +  }
    +})
    
  • packages/playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts+22 0 added
    @@ -0,0 +1,22 @@
    +import { isBuild } from '../../../testUtils'
    +
    +describe('main', () => {
    +  if (!isBuild) {
    +    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)
    +    })
    +  } else {
    +    test('dummy test to make jest happy', async () => {
    +      // Your test suite must contain at least one test.
    +    })
    +  }
    +})
    
  • packages/playground/fs-serve/__tests__/deny/vite.config.js+1 0 added
    @@ -0,0 +1 @@
    +module.exports = require('../../root/vite.config-deny')
    
  • packages/vite/src/node/server/middlewares/static.ts+9 3 modified
    @@ -156,7 +156,11 @@ export function serveRawFsMiddleware(
       }
     }
     
    -const _matchOptions = { matchBase: true, nocase: true }
    +const _matchOptions = {
    +  matchBase: false,
    +  nocase: true,
    +  dot: true
    +}
     
     export function isFileServingAllowed(
       url: string,
    @@ -166,8 +170,10 @@ export function isFileServingAllowed(
     
       const file = fsPathFromUrl(url)
     
    -  if (server.config.server.fs.deny.some((i) => isMatch(file, i, _matchOptions)))
    -    return false
    +  const deny = server.config.server.fs.deny.map((pattern) =>
    +    pattern.includes('/') ? pattern : `**/${pattern}`
    +  )
    +  if (deny.some((i) => isMatch(file, i, _matchOptions))) return false
     
       if (server.moduleGraph.safeModulesPath.has(file)) return true
     
    
89c7c645f09d

fix: port #16250 to v3 (#16253)

https://github.com/vitejs/vite翠 / greenMar 24, 2024via ghsa
7 files changed · +59 5
  • packages/vite/src/node/server/index.ts+13 4 modified
    @@ -452,10 +452,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
    +      }
    +    )
       }
     
       server.transformIndexHtml = createDevHtmlTransformFn(server)
    
  • playground/fs-serve/package.json+4 1 modified
    @@ -6,6 +6,9 @@
         "dev": "vite root",
         "build": "vite build root",
         "debug": "node --inspect-brk ../../packages/vite/bin/vite",
    -    "preview": "vite preview root"
    +    "preview": "vite preview root",
    +    "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"
       }
     }
    
  • playground/fs-serve/root/src/deny/.deny+1 0 added
    @@ -0,0 +1 @@
    +.deny
    
  • playground/fs-serve/root/src/deny/deny.txt+1 0 added
    @@ -0,0 +1 @@
    +deny
    
  • playground/fs-serve/root/vite.config-deny.js+22 0 added
    @@ -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, '/'))
    +  }
    +})
    
  • playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts+17 0 added
    @@ -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)
    +  })
    +})
    
  • playground/fs-serve/__tests__/deny/vite.config.js+1 0 added
    @@ -0,0 +1 @@
    +module.exports = require('../../root/vite.config-deny')
    
5a056dd2fc80

fix: `fs.deny` with globs with directories (#16250)

https://github.com/vitejs/vite翠 / greenMar 24, 2024via ghsa
6 files changed · +58 5
  • packages/vite/src/node/server/index.ts+13 4 modified
    @@ -646,10 +646,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,
       }
     
    
  • playground/fs-serve/package.json+4 1 modified
    @@ -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"
       }
     }
    
  • playground/fs-serve/root/src/deny/.deny+1 0 added
    @@ -0,0 +1 @@
    +.deny
    
  • playground/fs-serve/root/src/deny/deny.txt+1 0 added
    @@ -0,0 +1 @@
    +deny
    
  • playground/fs-serve/root/vite.config-deny.js+22 0 added
    @@ -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, '/')),
    +  },
    +})
    
  • playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts+17 0 added
    @@ -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)
    +  })
    +})
    
d2db33f7d4b9

fix: `fs.deny` with globs with directories (#16250)

https://github.com/vitejs/vite翠 / greenMar 24, 2024via ghsa
6 files changed · +58 5
  • packages/vite/src/node/server/index.ts+13 4 modified
    @@ -617,10 +617,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,
       }
     
    
  • playground/fs-serve/package.json+4 1 modified
    @@ -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"
       }
     }
    
  • playground/fs-serve/root/src/deny/.deny+1 0 added
    @@ -0,0 +1 @@
    +.deny
    
  • playground/fs-serve/root/src/deny/deny.txt+1 0 added
    @@ -0,0 +1 @@
    +deny
    
  • playground/fs-serve/root/vite.config-deny.js+22 0 added
    @@ -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, '/')),
    +  },
    +})
    
  • playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts+17 0 added
    @@ -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)
    +  })
    +})
    
96a7f3a41ef2

fix: `fs.deny` with globs with directories (#16250)

https://github.com/vitejs/vite翠 / greenMar 24, 2024via ghsa
6 files changed · +58 5
  • packages/vite/src/node/server/index.ts+13 4 modified
    @@ -509,10 +509,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,
       }
     
    
  • playground/fs-serve/package.json+4 1 modified
    @@ -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"
       }
     }
    
  • playground/fs-serve/root/src/deny/.deny+1 0 added
    @@ -0,0 +1 @@
    +.deny
    
  • playground/fs-serve/root/src/deny/deny.txt+1 0 added
    @@ -0,0 +1 @@
    +deny
    
  • playground/fs-serve/root/vite.config-deny.js+22 0 added
    @@ -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, '/')),
    +  },
    +})
    
  • playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts+17 0 added
    @@ -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)
    +  })
    +})
    
ba5269cca81d

fix: `fs.deny` with globs with directories (#16250)

https://github.com/vitejs/vite翠 / greenMar 24, 2024via ghsa
6 files changed · +58 5
  • packages/vite/src/node/server/index.ts+13 4 modified
    @@ -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,
       }
     
    
  • playground/fs-serve/package.json+4 1 modified
    @@ -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"
       }
     }
    
  • playground/fs-serve/root/src/deny/.deny+1 0 added
    @@ -0,0 +1 @@
    +.deny
    
  • playground/fs-serve/root/src/deny/deny.txt+1 0 added
    @@ -0,0 +1 @@
    +deny
    
  • playground/fs-serve/root/vite.config-deny.js+22 0 added
    @@ -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, '/')),
    +  },
    +})
    
  • playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts+17 0 added
    @@ -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)
    +  })
    +})
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

9

News mentions

0

No linked articles in our index yet.