---
id: 2026-10-vitest-5-dev-server-fs-deny-misapplied-mocker-code-injection-cve-2026-112948-112949-112950
title: "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"
date_disclosed: 2026-10-16
last_updated: 2026-10-22
severity: medium
status: patched
ecosystems: [npm, javascript, vite, testing, local-dev]
tools_affected: ["vitest, @vitest/ui, @vitest/browser 5.0.0-beta.6 before 5.0.5; vite-plus 1.0.0-rc.0 before 1.3.0 (CVE-2026-112948)", "@vitest/mocker 2.1.0-beta.7 before 4.1.12 and 5.0.0 before 5.0.3 (CVE-2026-112949)", "@vitest/mocker 4.1.11 and 5.0.0-rc.2 before 5.0.3 on Windows (CVE-2026-112950)", "vite 6.4.4 (GHSA-8g5g-mxqh-grgj, fixed 6.4.5)", "only when Vitest runs an HTTP server: --ui, Browser Mode, or api enabled; plain vitest and vitest run are not affected"]
tags: [cve, ghsa, vitest, vite, dev-server, fs-deny, env-exposure, api-token, mocker, code-injection, path-traversal, windows, patch-bypass, local-dev]
---

## 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](2026-07-vitest-browser-mode-cdp-rce.md). 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](../playbooks/rotating-cloud-credentials.md), [if your local AI agent was exploited](../playbooks/if-your-local-ai-agent-was-exploited.md).

## Prevention

- [Agent sandboxing](../prevention/agent-sandboxing.md): dev and test servers on loopback, in a container, without the project's real `.env`.
- [Credential hygiene](../prevention/credential-hygiene.md).

## Sources
- [vitest-dev/vitest — GHSA-p458-7748-mcp3: Servers misapply `server.fs.deny`, serving `.env`, private keys, `.git`, and the API token file](https://github.com/advisories/GHSA-p458-7748-mcp3) — fetched 2026-10-22: CVE-2026-112948, 6.5 and vector, the three affected packages and `vite-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](https://github.com/advisories/GHSA-qxg6-89mg-rqv8) — fetched 2026-10-22: CVE-2026-112949, 4.7 and vector, the ranges, the `manual` branch left by the earlier fix, the origin-check limit, the `JSON.stringify` fix, credits.
- [vitest-dev/vitest — GHSA-xp26-3454-mjgp: Windows backslash traversal bypasses the @vitest/mocker redirect allowlist fix](https://github.com/vitest-dev/vitest/security/advisories/GHSA-xp26-3454-mjgp) — 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.deny` bypassed with queries for v6](https://github.com/vitejs/vite/security/advisories/GHSA-8g5g-mxqh-grgj) — 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](https://cveawg.mitre.org/api/cve/CVE-2026-112948) and [CVE-2026-112949](https://cveawg.mitre.org/api/cve/CVE-2026-112949) — fetched 2026-10-22: GitHub CNA, published 2026-10-20, the ranges and scores above.
- [vitest-dev/vitest — security advisories tab](https://github.com/vitest-dev/vitest/security/advisories) and [vitejs/vite — security advisories tab](https://github.com/vitejs/vite/security/advisories) — fetched 2026-10-22: the three 2026-10-16 rows and the 2026-10-21 row.
- npm registry `time` for `vitest` — 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)"](https://hn.algolia.com/api/v1/search_by_date?query=CVE&tags=story) — read 2026-10-22: story dated 2026-10-22 linking the advisory.
