medium

CVE-2026-112948

npm · @vitest/ui

Summary

Vitest: Servers misapply `server.fs.deny`, serving `.env`, private keys, `.git`, and the API token file

Severity
medium
CVSS
6.5
EPSS
0.4% (p34)
CWE
CWE-200, CWE-552
Also known as
GHSA-p458-7748-mcp3#@vitest/ui
Published
2026-10-21
Updated
2026-10-21

Advisory details

Summary

In Vitest 5, Vite's server.fs.deny is not applied as intended on Vitest's dev servers. Depending on the server, files that Vite refuses to serve by default (such as .env, private keys and certificates, .npmrc, and .git) or Vitest's own API token file (.vitest-secret-token) can be read over plain HTTP by a client that can reach the server. In Browser Mode with test.projects, a malicious website can also read .env values through the developer's browser.

This only applies when Vitest runs an HTTP server, which happens with the UI (--ui), Browser Mode, or api enabled. Plain vitest and vitest run don't listen on any port and are not affected. The fix ships in vitest, and @vitest/ui and @vitest/browser are listed because they are what enables the affected setups. Both pin vitest to the same version as a peer dependency, so upgrading either one also requires the patched vitest. Users who enable api without @vitest/ui or @vitest/browser are also affected and should upgrade vitest.

Details

Vitest 5 adds its API token file to server.fs.deny, but neither server ended up with the intended list. That's because of two Vite behaviors. Vite applies its default deny list only when server.fs.deny is unset, and it compiles the list into a matcher during config resolution, so later changes to the array have no effect.

setup listening server Vite's default deny list .vitest-secret-token
plain vitest / vitest run none not reachable not reachable
--ui or api root denied served (fallback location only)
Browser Mode, single project root (also the browser server) denied served (fallback location only)
Browser Mode with test.projects each browser project's server served denied

Impact

Information disclosure from the Vitest dev server, and with the token, privileged API access.

Only the machine running Vitest is exposed, while it runs one of the setups above. Applications built or deployed from the project aren't affected.

The fix is in vitest <PATCHED>. Vitest 4 and earlier are unaffected. They don't persist an API token, and they don't override server.fs.deny.

Workaround

Set server.fs.deny explicitly in the root Vitest config, including Vite's default list for your Vite version and the token file. For Vite 8.3:

export default defineConfig({
  server: {
    fs: {
      deny: [
        '.env',
        '.env.*',
        '*.{crt,pem,key,p12,pfx,cer,der}',
        '.npmrc',
        '.yarnrc.yml',
        '**/.git/**',
        '.vitest-secret-token',
      ],
    },
  },
})

References

Related advisories

Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.

Check my repo

Summarize with AI

ChatGPTClaudePerplexity

Sources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.