TL;DR

Three Vitest advisories published 2026-10-16 and listed by the GitHub Advisory Database on 2026-10-21. CVE-2026-112948 (GHSA-p458-7748-mcp3, 6.5): in Vitest 5 the dev servers behind --ui, Browser Mode and api misapplied Vite's server.fs.deny, so .env, private keys and certificates, .npmrc, .git and Vitest's own API token file were readable over HTTP by anyone who could reach the server, and in Browser Mode with test.projects a malicious website could read .env values through the developer's browser; fixed 5.0.5. CVE-2026-112949 (GHSA-qxg6-89mg-rqv8, 4.7): @vitest/mocker's interceptor accepted manual mock registrations over the dev-server WebSocket without authentication and inserted the mock URL unescaped into generated module source, so a non-browser client on the port could replace a project module with its own JavaScript in the developer's browser; fixed 4.1.12 and 5.0.3. CVE-2026-112950 (GHSA-xp26-3454-mjgp, 5.9): the August fix for the mocker's redirect allowlist used a POSIX join, so on Windows a backslash escaped the root; fixed 4.1.12 and 5.0.3. Vite itself published GHSA-8g5g-mxqh-grgj on 2026-10-21: 6.4.4 back-ported one deny-list fix without its companion and serves denied files with ?raw-style queries; fixed 6.4.5. All of it is development-only, and only the machine running the server is exposed, not anything built from the project.

What happened

CVE-2026-112948. Vite applies its default deny list only when server.fs.deny is unset; Vitest's project servers replaced the list and the root server added .vitest-secret-token after Vite had compiled its matcher, so the defaults were lost. Files Vite normally blocks could be read over HTTP, plus the API token at node_modules/.vitest-secret-token, which grants privileged API access. In Browser Mode with test.projects, a malicious site could include .env as a classic script and read values that happen to be valid JavaScript; Chrome may first ask for Local Network Access permission. Affected vitest, @vitest/ui and @vitest/browser 5.0.0-beta.6 before 5.0.5 (the UI and browser packages pin vitest as a peer at the same version) and vite-plus 1.0.0-rc.0 before 1.3.0; Vitest 4 and earlier are not affected. CVSS 3.1 6.5 (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N), CWE-200, CWE-552. Workaround: set server.fs.deny explicitly in the root Vitest config with Vite's defaults plus .vitest-secret-token. Reporter sondt99, finder tomohiro86; PR #11578, release v5.0.5.

CVE-2026-112949. interceptorPlugin accepts mock registrations over Vite's WebSocket with no authentication, and createManualModuleSource inserted the attacker-controlled url unescaped; the earlier fix for GHSA-82fw-gwwq-j7x9 hardened only the redirect branch. Vite's origin check blocks browser cross-origin callers, so the practical attacker is a non-browser WebSocket client with access to the port; configureServer does not run during vite build or vite preview. CVSS 3.1 4.7 (AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N), CWE-94, CWE-116, CWE-306. Fixed by serialising the module URL and export names with JSON.stringify, in 4.1.12 and 5.0.3. Reporter Thai Son Dinh (VinSOC Labs, sondt99).

CVE-2026-112950. The GHSA-82fw-gwwq-j7x9 fix joined the redirect pathname to the Vite root with node:path/posix, so ..\ survived the allowlist check while readFile() treated the backslash as a separator and read outside the root on Windows. Affected @vitest/mocker 4.1.11 and 5.0.0-rc.2 before 5.0.3; CVSS 3.1 5.9, CWE-22; PR #11377 (the patch note dates the fix 2026-09-30). Reporter jankesec.

Vite GHSA-8g5g-mxqh-grgj (2026-10-21). vite 6.4.4 back-ported the fix for GHSA-rq7h-c2jc-7f22 (PR #20410) without PR #22160, so v6 stayed open to GHSA-v2wj-q39q-566r: denied files return with ?raw, ?import&raw or ?import&url&inline. Only when the dev server is exposed with --host or server.host, the file is under server.fs.allow, and a deny pattern matches it. CVSS 4.0 6.9, CWE-180, CWE-284; fixed 6.4.5. Reporter Hama1cco.

Registry. npm time, read 2026-10-22: vitest 5.0.4 on 2026-10-12, 5.0.5 and 4.1.12 on 2026-10-15, 5.1.0-beta.1 on 10-19. The Vitest tab (read 2026-10-22) holds ten advisories; the four critical ones from May to July are in the browser-mode file. The Storybook advisories of 2026-10-12 tell Storybook users to move Vitest to 3.2.7 or 4.1.10 and Vite to 6.4.2, 7.3.2 or 8.0.5; those are earlier fixes than the ones here.

Why it is here: Vitest is the test runner Vite, SvelteKit, Nuxt and most generated React projects ship with, --ui and Browser Mode are what an agent reaches for to debug a failing test, and .env on a developer machine holds the provider keys.

Am I affected?

  • npm ls vitest @vitest/ui @vitest/browser @vitest/mocker vite vite-plus; compare with the frontmatter ranges.
  • Exposure for CVE-2026-112948 needs an HTTP server: vitest --ui, Browser Mode, or api: true. Plain vitest and vitest run are not affected. The token-file read needs a client that can reach the server; the .env-through-browser path needs a malicious site open while Browser Mode with test.projects runs.
  • The mocker bugs need a client on the dev-server port (or, for the Windows one, a Vite HMR WebSocket) and a project using mockerPlugin() or interceptorPlugin().
  • The Vite 6.4.4 bug needs an exposed host.

If you are affected

  1. Upgrade vitest and its UI and browser packages to 5.0.5 (or 4.1.12 on the 4 line), @vitest/mocker with them, vite-plus to 1.3.0, and vite 6 to 6.4.5.
  2. Until then, set server.fs.deny explicitly as the advisory shows, and do not expose the server with --host.
  3. If a Vitest 5 server with --ui, Browser Mode or api was reachable from other machines, or Browser Mode ran while you browsed, rotate the values in .env and any key or certificate under the project root, and delete node_modules/.vitest-secret-token: rotating cloud credentials, if your local AI agent was exploited.

Prevention

Sources