CVE-2026-47429 Overview
CVE-2026-47429 is a path traversal and arbitrary script execution vulnerability in Vitest, a testing framework powered by Vite. On Windows, the Vitest UI/API server used isFileServingAllowed incorrectly for the /__vitest_attachment__ endpoint. This flaw allows \\?\..\ path traversal sequences to read files outside the project root. Exposed API write and rerun features such as saveTestFile and rerun further allow attackers to execute arbitrary scripts on the host. The issue affects Vitest versions prior to 3.2.5 and 4.1.0 and is tracked under [CWE-22]. The maintainers fixed the flaw in versions 3.2.5 and 4.1.0.
Critical Impact
A remote unauthenticated attacker who can reach the Vitest API server can read arbitrary files on Windows hosts and execute arbitrary scripts through exposed write and rerun endpoints.
Affected Products
- Vitest versions prior to 3.2.5 (v3.x branch)
- Vitest versions prior to 4.1.0 (v4.x branch)
- Vitest UI/API server deployments on Windows
Discovery Timeline
- 2026-07-14 - CVE-2026-47429 published to NVD
- 2026-07-15 - Last updated in NVD database
Technical Details for CVE-2026-47429
Vulnerability Analysis
Vitest exposes an HTTP endpoint at /__vitest_attachment__ that serves files referenced by test attachments. The endpoint gates access using isFileServingAllowed, a Vite helper that checks whether a requested path falls within the allowed serving directories. On Windows, the check does not correctly normalize paths containing the \\?\ extended-length prefix, allowing sequences such as \\?\..\ to bypass the boundary check.
Beyond file disclosure, the Vitest API server exposes write and rerun commands including saveTestFile and rerun. When the API server is exposed to untrusted networks, these commands allow an attacker to write attacker-controlled JavaScript into test files and trigger reruns, resulting in arbitrary script execution in the Node.js process running Vitest.
Root Cause
The root cause is improper limitation of a pathname to a restricted directory [CWE-22]. isFileServingAllowed was intended for read-through file serving and did not account for Windows extended-length path syntax. The fix migrates the attachment endpoint to isFileLoadingAllowed, which validates against the resolved configuration. Additionally, the API server previously had no gating for destructive commands. The patch introduces allowWrite and allowExec options that must be explicitly enabled.
Attack Vector
An attacker on the network reaches the Vitest UI/API server, typically bound to a local port during development. Using a crafted request such as GET /__vitest_attachment__?path=\\?\..\..\Windows\win.ini, the attacker retrieves files outside the project. To achieve code execution, the attacker calls saveTestFile with malicious JavaScript, then invokes rerun to execute it in the Vitest runner context.
// Patch: packages/browser/src/node/commands/fs.ts
import fs, { promises as fsp } from 'node:fs'
import { basename, dirname, resolve } from 'node:path'
import mime from 'mime/lite'
-import { isFileServingAllowed } from 'vitest/node'
+import { isFileLoadingAllowed } from 'vitest/node'
+import { slash } from '../utils'
function assertFileAccess(path: string, project: TestProject) {
if (
- !isFileServingAllowed(path, project.vite)
- && !isFileServingAllowed(path, project.vitest.vite)
+ !isFileLoadingAllowed(project.vite.config, path)
+ && !isFileLoadingAllowed(project.vitest.vite.config, path)
) {
throw new Error(
`Access denied to "${path}". See Vite config documentation for "server.fs".`,
)
}
}
+function assertWrite(path: string, project: TestProject) {
+ if (!project.config.browser.api.allowWrite || !project.vitest.config.api.allowWrite) {
+ throw new Error(`Cannot modify file "${path}". File writing is disabled because server is exposed to the internet.`)
+ }
+}
Source: GitHub Commit 20e00ef
Detection Methods for CVE-2026-47429
Indicators of Compromise
- HTTP requests to /__vitest_attachment__ containing \\?\, %5C%5C%3F%5C, or ..\ path traversal sequences.
- Unexpected invocations of Vitest API methods saveTestFile, readFile, or rerun from remote clients.
- Modification of test files under the project directory outside developer working hours.
- Vitest API server bound to 0.0.0.0 or otherwise reachable from non-loopback interfaces.
Detection Strategies
- Inspect reverse proxy and web server logs for requests targeting the /__vitest_attachment__ path on ports commonly used by Vite dev servers.
- Monitor Node.js process telemetry for unexpected child processes spawned by vitest or node running test files.
- Audit developer workstations and CI runners on Windows for exposed Vitest ports using host-based network inventory.
Monitoring Recommendations
- Alert on inbound connections to Vitest dev server ports originating from non-localhost sources.
- Track file write events to *.test.ts, *.test.js, *.spec.ts, and *.spec.js files initiated by network-facing processes.
- Baseline expected Vitest API call patterns in CI environments and flag deviations.
How to Mitigate CVE-2026-47429
Immediate Actions Required
- Upgrade Vitest to version 3.2.5 or 4.1.0 or later using npm install vitest@^3.2.5 or npm install vitest@^4.1.0.
- Ensure the Vitest UI/API server is bound to localhost only and never exposed to untrusted networks.
- Audit CI/CD pipelines and developer environments on Windows for exposed Vitest ports.
- Review recent test file changes for unauthorized modifications indicating exploitation.
Patch Information
The maintainers released fixes in Vitest v3.2.5 and Vitest v4.1.0. The fix replaces isFileServingAllowed with isFileLoadingAllowed for the attachment endpoint and introduces new allowWrite and allowExec API options that default to disabled. See the GitHub Security Advisory GHSA-5xrq-8626-4rwp and Pull Request #9350 for details.
Workarounds
- Bind the Vitest server to 127.0.0.1 and disable UI mode when exposure is not required.
- Place the Vitest port behind firewall rules restricting access to trusted developer IPs.
- Do not run Vitest UI on shared or internet-reachable hosts until patched.
# vitest.config.ts - restrict server exposure
export default defineConfig({
test: {
api: {
host: '127.0.0.1',
port: 51204,
allowWrite: false,
allowExec: false,
},
},
})
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

