VYPR
Medium severity4.8NVD Advisory· Published Sep 17, 2024· Updated Apr 15, 2026

CVE-2024-45811

CVE-2024-45811

Description

Vite a frontend build tooling framework for javascript. In affected versions the contents of arbitrary files can be returned to the browser. @fs denies access to files outside of Vite serving allow list. Adding ?import&raw to the URL bypasses this limitation and returns the file content if it exists. This issue has been patched in versions 5.4.6, 5.3.6, 5.2.14, 4.5.5, and 3.2.11. Users are advised to upgrade. There are no known workarounds for this vulnerability.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
vitenpm
>= 5.4.0, < 5.4.65.4.6
vitenpm
>= 5.3.0, < 5.3.65.3.6
vitenpm
>= 5.2.0, < 5.2.145.2.14
vitenpm
>= 4.0.0, < 4.5.44.5.4
vitenpm
< 3.2.113.2.11
vitenpm
>= 5.0.0, < 5.1.85.1.8

Patches

10
b901438f99e6

fix: backport #18112, fs raw query

https://github.com/vitejs/vitepatak-devSep 16, 2024via ghsa
5 files changed · +36 3
  • packages/vite/src/node/plugins/asset.ts+1 1 modified
    @@ -29,7 +29,7 @@ import { FS_PREFIX } from '../constants'
     
     export const assetUrlRE = /__VITE_ASSET__([a-z\d]+)__(?:\$_(.*?)__)?/g
     
    -const rawRE = /(?:\?|&)raw(?:&|$)/
    +export const rawRE = /(?:\?|&)raw(?:&|$)/
     export const urlRE = /(\?|&)url(?:&|$)/
     const jsSourceMapRE = /\.[cm]?js\.map$/
     const unnededFinalQueryCharRE = /[?&]$/
    
  • packages/vite/src/node/server/middlewares/static.ts+1 1 modified
    @@ -211,7 +211,7 @@ export function isFileServingAllowed(
       return false
     }
     
    -function ensureServingAccess(
    +export function ensureServingAccess(
       url: string,
       server: ViteDevServer,
       res: ServerResponse,
    
  • packages/vite/src/node/server/middlewares/transform.ts+9 1 modified
    @@ -38,7 +38,8 @@ import {
     } from '../../plugins/optimizedDeps'
     import { ERR_CLOSED_SERVER } from '../pluginContainer'
     import { getDepsOptimizer } from '../../optimizer'
    -import { urlRE } from '../../plugins/asset'
    +import { rawRE, urlRE } from '../../plugins/asset'
    +import { ensureServingAccess } from './static'
     
     const debugCache = createDebugger('vite:cache')
     
    @@ -166,6 +167,13 @@ export function transformMiddleware(
             }
           }
     
    +      if (
    +        (rawRE.test(url) || urlRE.test(url)) &&
    +        !ensureServingAccess(url, server, res, next)
    +      ) {
    +        return
    +      }
    +
           if (
             isJSRequest(url) ||
             isImportRequest(url) ||
    
  • playground/fs-serve/root/src/index.html+20 0 modified
    @@ -35,6 +35,8 @@ <h2>Safe /@fs/ Fetch</h2>
     <h2>Unsafe /@fs/ Fetch</h2>
     <pre class="unsafe-fs-fetch-status"></pre>
     <pre class="unsafe-fs-fetch"></pre>
    +<pre class="unsafe-fs-fetch-raw-status"></pre>
    +<pre class="unsafe-fs-fetch-raw"></pre>
     <pre class="unsafe-fs-fetch-8498-status"></pre>
     <pre class="unsafe-fs-fetch-8498"></pre>
     <pre class="unsafe-fs-fetch-8498-2-status"></pre>
    @@ -188,6 +190,24 @@ <h2>Denied</h2>
           console.error(e)
         })
     
    +  // not imported before, outside of root, treated as unsafe
    +  fetch(
    +    joinUrlSegments(
    +      base,
    +      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',
    +    ),
    +  )
    +    .then((r) => {
    +      text('.unsafe-fs-fetch-raw-status', r.status)
    +      return r.json()
    +    })
    +    .then((data) => {
    +      text('.unsafe-fs-fetch-raw', JSON.stringify(data))
    +    })
    +    .catch((e) => {
    +      console.error(e)
    +    })
    +
       // outside root with special characters #8498
       fetch(
         joinUrlSegments(
    
  • playground/fs-serve/__tests__/fs-serve.spec.ts+5 0 modified
    @@ -77,6 +77,11 @@ describe.runIf(isServe)('main', () => {
         expect(await page.textContent('.unsafe-fs-fetch-status')).toBe('403')
       })
     
    +  test('unsafe fs fetch', async () => {
    +    expect(await page.textContent('.unsafe-fs-fetch-raw')).toBe('')
    +    expect(await page.textContent('.unsafe-fs-fetch-raw-status')).toBe('403')
    +  })
    +
       test('unsafe fs fetch with special characters (#8498)', async () => {
         expect(await page.textContent('.unsafe-fs-fetch-8498')).toBe('')
         expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('404')
    
a6da45082b6e

fix: backport #18112, fs raw query

https://github.com/vitejs/vitepatak-devSep 16, 2024via ghsa
5 files changed · +37 3
  • packages/vite/src/node/plugins/asset.ts+2 2 modified
    @@ -29,8 +29,8 @@ export const duplicateAssets = new WeakMap<
       Map<string, OutputAsset>
     >()
     
    -const rawRE = /(\?|&)raw(?:&|$)/
    -const urlRE = /(\?|&)url(?:&|$)/
    +export const rawRE = /(\?|&)raw(?:&|$)/
    +export const urlRE = /(\?|&)url(?:&|$)/
     
     const assetCache = new WeakMap<ResolvedConfig, Map<string, string>>()
     
    
  • packages/vite/src/node/server/middlewares/static.ts+1 1 modified
    @@ -174,7 +174,7 @@ export function isFileServingAllowed(
       return false
     }
     
    -function ensureServingAccess(
    +export function ensureServingAccess(
       url: string,
       server: ViteDevServer,
       res: ServerResponse,
    
  • packages/vite/src/node/server/middlewares/transform.ts+9 0 modified
    @@ -35,6 +35,8 @@ import {
       ERR_OUTDATED_OPTIMIZED_DEP
     } from '../../plugins/optimizedDeps'
     import { getDepsOptimizer } from '../../optimizer'
    +import { rawRE, urlRE } from '../../plugins/asset'
    +import { ensureServingAccess } from './static'
     
     const debugCache = createDebugger('vite:cache')
     const isDebug = !!process.env.DEBUG
    @@ -147,6 +149,13 @@ export function transformMiddleware(
             }
           }
     
    +      if (
    +        (rawRE.test(url) || urlRE.test(url)) &&
    +        !ensureServingAccess(url, server, res, next)
    +      ) {
    +        return
    +      }
    +
           if (
             isJSRequest(url) ||
             isImportRequest(url) ||
    
  • playground/fs-serve/root/src/index.html+20 0 modified
    @@ -35,6 +35,8 @@ <h2>Safe /@fs/ Fetch</h2>
     <h2>Unsafe /@fs/ Fetch</h2>
     <pre class="unsafe-fs-fetch-status"></pre>
     <pre class="unsafe-fs-fetch"></pre>
    +<pre class="unsafe-fs-fetch-raw-status"></pre>
    +<pre class="unsafe-fs-fetch-raw"></pre>
     <pre class="unsafe-fs-fetch-8498-status"></pre>
     <pre class="unsafe-fs-fetch-8498"></pre>
     <pre class="unsafe-fs-fetch-8498-2-status"></pre>
    @@ -166,6 +168,24 @@ <h2>Denied</h2>
           console.error(e)
         })
     
    +  // not imported before, outside of root, treated as unsafe
    +  fetch(
    +    joinUrlSegments(
    +      base,
    +      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',
    +    ),
    +  )
    +    .then((r) => {
    +      text('.unsafe-fs-fetch-raw-status', r.status)
    +      return r.json()
    +    })
    +    .then((data) => {
    +      text('.unsafe-fs-fetch-raw', JSON.stringify(data))
    +    })
    +    .catch((e) => {
    +      console.error(e)
    +    })
    +
       // outside root with special characters #8498
       fetch('/@fs/' + ROOT + '/root/src/%2e%2e%2f%2e%2e%2funsafe%2ejson')
         .then((r) => {
    
  • playground/fs-serve/__tests__/fs-serve.spec.ts+5 0 modified
    @@ -76,6 +76,11 @@ describe.runIf(isServe)('main', () => {
         expect(await page.textContent('.unsafe-fs-fetch-status')).toBe('403')
       })
     
    +  test('unsafe fs fetch', async () => {
    +    expect(await page.textContent('.unsafe-fs-fetch-raw')).toBe('')
    +    expect(await page.textContent('.unsafe-fs-fetch-raw-status')).toBe('403')
    +  })
    +
       test('unsafe fs fetch with special characters (#8498)', async () => {
         expect(await page.textContent('.unsafe-fs-fetch-8498')).toBe('')
         expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('403')
    
8339d7408668

fix: fs raw query (#18112)

https://github.com/vitejs/vitepatakSep 16, 2024via ghsa
4 files changed · +35 1
  • packages/vite/src/node/server/middlewares/static.ts+1 1 modified
    @@ -229,7 +229,7 @@ export function isFileServingAllowed(
       return false
     }
     
    -function ensureServingAccess(
    +export function ensureServingAccess(
       url: string,
       server: ViteDevServer,
       res: ServerResponse,
    
  • packages/vite/src/node/server/middlewares/transform.ts+9 0 modified
    @@ -12,6 +12,7 @@ import {
       isJSRequest,
       normalizePath,
       prettifyUrl,
    +  rawRE,
       removeImportQuery,
       removeTimestampQuery,
       urlRE,
    @@ -35,6 +36,7 @@ import { ERR_CLOSED_SERVER } from '../pluginContainer'
     import { getDepsOptimizer } from '../../optimizer'
     import { cleanUrl, unwrapId, withTrailingSlash } from '../../../shared/utils'
     import { NULL_BYTE_PLACEHOLDER } from '../../../shared/constants'
    +import { ensureServingAccess } from './static'
     
     const debugCache = createDebugger('vite:cache')
     
    @@ -158,6 +160,13 @@ export function transformMiddleware(
             warnAboutExplicitPublicPathInUrl(url)
           }
     
    +      if (
    +        (rawRE.test(url) || urlRE.test(url)) &&
    +        !ensureServingAccess(url, server, res, next)
    +      ) {
    +        return
    +      }
    +
           if (
             isJSRequest(url) ||
             isImportRequest(url) ||
    
  • playground/fs-serve/root/src/index.html+20 0 modified
    @@ -35,6 +35,8 @@ <h2>Safe /@fs/ Fetch</h2>
     <h2>Unsafe /@fs/ Fetch</h2>
     <pre class="unsafe-fs-fetch-status"></pre>
     <pre class="unsafe-fs-fetch"></pre>
    +<pre class="unsafe-fs-fetch-raw-status"></pre>
    +<pre class="unsafe-fs-fetch-raw"></pre>
     <pre class="unsafe-fs-fetch-8498-status"></pre>
     <pre class="unsafe-fs-fetch-8498"></pre>
     <pre class="unsafe-fs-fetch-8498-2-status"></pre>
    @@ -188,6 +190,24 @@ <h2>Denied</h2>
           console.error(e)
         })
     
    +  // not imported before, outside of root, treated as unsafe
    +  fetch(
    +    joinUrlSegments(
    +      base,
    +      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',
    +    ),
    +  )
    +    .then((r) => {
    +      text('.unsafe-fs-fetch-raw-status', r.status)
    +      return r.json()
    +    })
    +    .then((data) => {
    +      text('.unsafe-fs-fetch-raw', JSON.stringify(data))
    +    })
    +    .catch((e) => {
    +      console.error(e)
    +    })
    +
       // outside root with special characters #8498
       fetch(
         joinUrlSegments(
    
  • playground/fs-serve/__tests__/fs-serve.spec.ts+5 0 modified
    @@ -77,6 +77,11 @@ describe.runIf(isServe)('main', () => {
         expect(await page.textContent('.unsafe-fs-fetch-status')).toBe('403')
       })
     
    +  test('unsafe fs fetch', async () => {
    +    expect(await page.textContent('.unsafe-fs-fetch-raw')).toBe('')
    +    expect(await page.textContent('.unsafe-fs-fetch-raw-status')).toBe('403')
    +  })
    +
       test('unsafe fs fetch with special characters (#8498)', async () => {
         expect(await page.textContent('.unsafe-fs-fetch-8498')).toBe('')
         expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('404')
    
6820bb3b9a54

fix: fs raw query (#18112)

https://github.com/vitejs/vitepatakSep 16, 2024via ghsa
4 files changed · +35 1
  • packages/vite/src/node/server/middlewares/static.ts+1 1 modified
    @@ -232,7 +232,7 @@ export function isFileServingAllowed(
       return false
     }
     
    -function ensureServingAccess(
    +export function ensureServingAccess(
       url: string,
       server: ViteDevServer,
       res: ServerResponse,
    
  • packages/vite/src/node/server/middlewares/transform.ts+9 0 modified
    @@ -12,6 +12,7 @@ import {
       isJSRequest,
       normalizePath,
       prettifyUrl,
    +  rawRE,
       removeImportQuery,
       removeTimestampQuery,
       urlRE,
    @@ -35,6 +36,7 @@ import { ERR_CLOSED_SERVER } from '../pluginContainer'
     import { getDepsOptimizer } from '../../optimizer'
     import { cleanUrl, unwrapId, withTrailingSlash } from '../../../shared/utils'
     import { NULL_BYTE_PLACEHOLDER } from '../../../shared/constants'
    +import { ensureServingAccess } from './static'
     
     const debugCache = createDebugger('vite:cache')
     
    @@ -161,6 +163,13 @@ export function transformMiddleware(
             warnAboutExplicitPublicPathInUrl(url)
           }
     
    +      if (
    +        (rawRE.test(url) || urlRE.test(url)) &&
    +        !ensureServingAccess(url, server, res, next)
    +      ) {
    +        return
    +      }
    +
           if (
             isJSRequest(url) ||
             isImportRequest(url) ||
    
  • playground/fs-serve/root/src/index.html+20 0 modified
    @@ -35,6 +35,8 @@ <h2>Safe /@fs/ Fetch</h2>
     <h2>Unsafe /@fs/ Fetch</h2>
     <pre class="unsafe-fs-fetch-status"></pre>
     <pre class="unsafe-fs-fetch"></pre>
    +<pre class="unsafe-fs-fetch-raw-status"></pre>
    +<pre class="unsafe-fs-fetch-raw"></pre>
     <pre class="unsafe-fs-fetch-8498-status"></pre>
     <pre class="unsafe-fs-fetch-8498"></pre>
     <pre class="unsafe-fs-fetch-8498-2-status"></pre>
    @@ -188,6 +190,24 @@ <h2>Denied</h2>
           console.error(e)
         })
     
    +  // not imported before, outside of root, treated as unsafe
    +  fetch(
    +    joinUrlSegments(
    +      base,
    +      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',
    +    ),
    +  )
    +    .then((r) => {
    +      text('.unsafe-fs-fetch-raw-status', r.status)
    +      return r.json()
    +    })
    +    .then((data) => {
    +      text('.unsafe-fs-fetch-raw', JSON.stringify(data))
    +    })
    +    .catch((e) => {
    +      console.error(e)
    +    })
    +
       // outside root with special characters #8498
       fetch(
         joinUrlSegments(
    
  • playground/fs-serve/__tests__/fs-serve.spec.ts+5 0 modified
    @@ -77,6 +77,11 @@ describe.runIf(isServe)('main', () => {
         expect(await page.textContent('.unsafe-fs-fetch-status')).toBe('403')
       })
     
    +  test('unsafe fs fetch', async () => {
    +    expect(await page.textContent('.unsafe-fs-fetch-raw')).toBe('')
    +    expect(await page.textContent('.unsafe-fs-fetch-raw-status')).toBe('403')
    +  })
    +
       test('unsafe fs fetch with special characters (#8498)', async () => {
         expect(await page.textContent('.unsafe-fs-fetch-8498')).toBe('')
         expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('404')
    
4573a6fd6f1b

fix: fs raw query (#18112)

https://github.com/vitejs/vitepatakSep 16, 2024via ghsa
4 files changed · +35 1
  • packages/vite/src/node/server/middlewares/static.ts+1 1 modified
    @@ -229,7 +229,7 @@ export function isFileServingAllowed(
       return false
     }
     
    -function ensureServingAccess(
    +export function ensureServingAccess(
       url: string,
       server: ViteDevServer,
       res: ServerResponse,
    
  • packages/vite/src/node/server/middlewares/transform.ts+9 0 modified
    @@ -12,6 +12,7 @@ import {
       isJSRequest,
       normalizePath,
       prettifyUrl,
    +  rawRE,
       removeImportQuery,
       removeTimestampQuery,
       urlRE,
    @@ -35,6 +36,7 @@ import { ERR_CLOSED_SERVER } from '../pluginContainer'
     import { getDepsOptimizer } from '../../optimizer'
     import { cleanUrl, unwrapId, withTrailingSlash } from '../../../shared/utils'
     import { NULL_BYTE_PLACEHOLDER } from '../../../shared/constants'
    +import { ensureServingAccess } from './static'
     
     const debugCache = createDebugger('vite:cache')
     
    @@ -158,6 +160,13 @@ export function transformMiddleware(
             warnAboutExplicitPublicPathInUrl(url)
           }
     
    +      if (
    +        (rawRE.test(url) || urlRE.test(url)) &&
    +        !ensureServingAccess(url, server, res, next)
    +      ) {
    +        return
    +      }
    +
           if (
             isJSRequest(url) ||
             isImportRequest(url) ||
    
  • playground/fs-serve/root/src/index.html+20 0 modified
    @@ -35,6 +35,8 @@ <h2>Safe /@fs/ Fetch</h2>
     <h2>Unsafe /@fs/ Fetch</h2>
     <pre class="unsafe-fs-fetch-status"></pre>
     <pre class="unsafe-fs-fetch"></pre>
    +<pre class="unsafe-fs-fetch-raw-status"></pre>
    +<pre class="unsafe-fs-fetch-raw"></pre>
     <pre class="unsafe-fs-fetch-8498-status"></pre>
     <pre class="unsafe-fs-fetch-8498"></pre>
     <pre class="unsafe-fs-fetch-8498-2-status"></pre>
    @@ -188,6 +190,24 @@ <h2>Denied</h2>
           console.error(e)
         })
     
    +  // not imported before, outside of root, treated as unsafe
    +  fetch(
    +    joinUrlSegments(
    +      base,
    +      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',
    +    ),
    +  )
    +    .then((r) => {
    +      text('.unsafe-fs-fetch-raw-status', r.status)
    +      return r.json()
    +    })
    +    .then((data) => {
    +      text('.unsafe-fs-fetch-raw', JSON.stringify(data))
    +    })
    +    .catch((e) => {
    +      console.error(e)
    +    })
    +
       // outside root with special characters #8498
       fetch(
         joinUrlSegments(
    
  • playground/fs-serve/__tests__/fs-serve.spec.ts+5 0 modified
    @@ -77,6 +77,11 @@ describe.runIf(isServe)('main', () => {
         expect(await page.textContent('.unsafe-fs-fetch-status')).toBe('403')
       })
     
    +  test('unsafe fs fetch', async () => {
    +    expect(await page.textContent('.unsafe-fs-fetch-raw')).toBe('')
    +    expect(await page.textContent('.unsafe-fs-fetch-raw-status')).toBe('403')
    +  })
    +
       test('unsafe fs fetch with special characters (#8498)', async () => {
         expect(await page.textContent('.unsafe-fs-fetch-8498')).toBe('')
         expect(await page.textContent('.unsafe-fs-fetch-8498-status')).toBe('404')
    

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

8

News mentions

0

No linked articles in our index yet.