Vitest 5 dev servers served .env, keys and the API token (CVE-2026-112948); mocker code injection and traversal bypass (CVE-2026-112949, CVE-2026-112950); fixed 5.0.5, 4.1.12
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, orapi: true. Plainvitestandvitest runare 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 withtest.projectsruns. - 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()orinterceptorPlugin(). - The Vite 6.4.4 bug needs an exposed host.
If you are affected
- Upgrade
vitestand its UI and browser packages to 5.0.5 (or 4.1.12 on the 4 line),@vitest/mockerwith them,vite-plusto 1.3.0, andvite6 to 6.4.5. - Until then, set
server.fs.denyexplicitly as the advisory shows, and do not expose the server with--host. - If a Vitest 5 server with
--ui, Browser Mode orapiwas reachable from other machines, or Browser Mode ran while you browsed, rotate the values in.envand any key or certificate under the project root, and deletenode_modules/.vitest-secret-token: rotating cloud credentials, if your local AI agent was exploited.
Prevention
- Agent sandboxing: dev and test servers on loopback, in a container, without the project's real
.env. - Credential hygiene.
Sources
- vitest-dev/vitest — GHSA-p458-7748-mcp3: Servers misapply
server.fs.deny, serving.env, private keys,.git, and the API token file — fetched 2026-10-22: CVE-2026-112948, 6.5 and vector, the three affected packages andvite-plus, the root cause, the Browser Mode path, "only the machine running Vitest is exposed," the workaround list, PR #11578, credits, published 2026-10-16. - vitest-dev/vitest — GHSA-qxg6-89mg-rqv8: Code injection via unauthenticated manual mock registration — fetched 2026-10-22: CVE-2026-112949, 4.7 and vector, the ranges, the
manualbranch left by the earlier fix, the origin-check limit, theJSON.stringifyfix, credits. - vitest-dev/vitest — GHSA-xp26-3454-mjgp: Windows backslash traversal bypasses the @vitest/mocker redirect allowlist fix — fetched 2026-10-22: CVE-2026-112950, 5.9, the POSIX-join root cause, the ranges, PR #11377 and its 2026-09-30 date, reporter.
- vitejs/vite — GHSA-8g5g-mxqh-grgj:
server.fs.denybypassed with queries for v6 — fetched 2026-10-22: published 2026-10-21, 6.9, the missing back-port, the three impact conditions, fixed 6.4.5, reporter. - CVE Services — CVE-2026-112948 and CVE-2026-112949 — fetched 2026-10-22: GitHub CNA, published 2026-10-20, the ranges and scores above.
- vitest-dev/vitest — security advisories tab and vitejs/vite — security advisories tab — fetched 2026-10-22: the three 2026-10-16 rows and the 2026-10-21 row.
- npm registry
timeforvitest— read 2026-10-22: 5.0.5 and 4.1.12 on 2026-10-15. - Hacker News (Algolia) — "Vitest Dev Server Secret Leak (CVE-2026-112948)" — read 2026-10-22: story dated 2026-10-22 linking the advisory.