Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-84373

CVE-2026-84373: Vitest Information Disclosure Vulnerability

CVE-2026-84373 is an information disclosure flaw in Vitest testing framework that allows remote attackers to read local files through unauthenticated HMR WebSocket. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-84373 Overview

CVE-2026-84373 is a path traversal vulnerability [CWE-22] in Vitest, a testing framework powered by Vite. The flaw exists in the mockerPlugin and interceptorPlugin exports within packages/mocker/src/node/interceptorPlugin.ts. These plugins register the vitest:interceptor:register handler on Vite's unauthenticated Hot Module Replacement (HMR) WebSocket without validating redirect targets against the file-serving allowlist. A remote client that reaches an exposed development server can submit a crafted URL preserving .. segments, causing the resolved path to escape the project root and disclose arbitrary local files readable by the dev-server process.

Critical Impact

Remote unauthenticated attackers who can reach a Vitest dev server can read arbitrary files accessible to the dev-server process, exposing source code, credentials, and configuration secrets.

Affected Products

  • Vitest versions 2.1.0 through 4.1.10
  • Vitest 5.0.0-rc.1 and earlier 5.x release candidates
  • Projects consuming @vitest/mockerinterceptorPlugin on an exposed dev server

Discovery Timeline

  • 2026-09-01 - CVE-2026-84373 published to NVD
  • 2026-09-02 - Last updated in NVD database
  • Fixed in - Vitest 4.1.11 and 5.0.0-rc.2

Technical Details for CVE-2026-84373

Vulnerability Analysis

The vulnerability originates in Vitest's mocker interceptor. When the plugin receives a vitest:interceptor:register event, it processes an event.redirect value without enforcing server.fs.allow and server.fs.deny through isFileLoadingAllowed. The plugin then executes join(server.config.root, redirectUrl.pathname), which resolves a traversal-laden path outside the project root. The plugin's load hook subsequently returns readFile(mock.redirect, 'utf-8') as module source, disclosing local file contents to the attacker.

Because registration occurs on the raw HMR WebSocket, no authentication token is required. Vitest browser mode uses a token-authenticated RPC and is not remotely unauthenticated by default, though the same boundary check was missing on that path.

Root Cause

The root cause is missing path canonicalization and allowlist enforcement before file reads. The handler trusts client-supplied redirect fields and constructs filesystem paths with join(), which preserves .. segments in opaque URL schemes. No call to checkFileAccess gated the resolved path prior to the fix.

Attack Vector

An attacker who can reach a listening Vitest dev server, for example on a shared network, exposed CI runner, or via DNS rebinding against a developer host, connects to the HMR WebSocket. The attacker sends a vitest:interceptor:register message containing a redirect URL such as mock:/../../etc/passwd. The server joins the pathname to the project root, escapes it, and returns the file contents to the caller.

typescript
// Security patch: packages/browser/src/node/rpc.ts
// Enforces file-access boundary before returning redirect content
if (module.type === 'redirect') {
  const redirectUrl = new URL(module.redirect)
  module.redirect = join(vite.config.root, redirectUrl.pathname)
  checkFileAccess(module.redirect)
}
defaultMockerRegistry.register(module)

Source: GitHub Commit 51edf2b

typescript
// Security patch: packages/browser/src/node/index.ts
// Browser mocks register through the authenticated RPC (setupBrowserRpc),
// so the raw dev-server socket must not accept mock registration
interceptorPlugin({ registry: mockerRegistry, registerWebSocketEvents: false }),

Source: GitHub Commit 8ff9b9a

Detection Methods for CVE-2026-84373

Indicators of Compromise

  • WebSocket messages to Vitest dev servers containing vitest:interceptor:register events with redirect values that include .. sequences or non-standard URL schemes.
  • Dev-server file reads outside server.config.root, especially of .env, ~/.ssh/, id_rsa, or credential stores.
  • Vitest dev server listening on non-loopback interfaces or reachable via a public port.

Detection Strategies

  • Inspect HMR WebSocket traffic for interceptor:register payloads originating from unexpected client addresses.
  • Enumerate running Node.js processes for Vitest versions between 2.1.0 and 4.1.10 using npm ls vitest or SBOM tooling.
  • Correlate dev-server process file-read telemetry with client sockets to identify path traversal patterns.

Monitoring Recommendations

  • Log all inbound connections to developer workstation ports commonly bound by Vite (5173, 51204) and alert on non-localhost sources.
  • Monitor CI/CD runners for Vitest dev servers that bind to 0.0.0.0 rather than 127.0.0.1.
  • Track outbound reads of sensitive files by Node.js processes tagged as test runners.

How to Mitigate CVE-2026-84373

Immediate Actions Required

  • Upgrade Vitest to 4.1.11 or 5.0.0-rc.2 across all development, CI, and preview environments.
  • Restrict Vitest dev servers to localhost bindings and block inbound WebSocket connections from untrusted networks.
  • Audit CI runners and cloud dev environments for exposed Vitest ports and rotate any secrets that may have been read from developer hosts.

Patch Information

The fix ships in Vitest 4.1.11 and 5.0.0-rc.2. The patch disables WebSocket event registration on the raw dev-server socket via registerWebSocketEvents: false and adds a checkFileAccess call that enforces server.fs.allow and server.fs.deny before returning redirect content. Reference: GitHub Security Advisory GHSA-82fw-gwwq-j7x9 and GitHub Pull Request #10972.

Workarounds

  • Bind the Vitest dev server to 127.0.0.1 only and never expose it via tunnels, reverse proxies, or --host flags.
  • Run Vitest inside an isolated container or VM with no access to secrets or SSH keys on the host filesystem.
  • Where feasible, disable the mocker interceptor plugin until upgrading to a patched version.
bash
# Configuration example: enforce loopback binding for Vitest dev server
# vitest.config.ts
export default defineConfig({
  server: {
    host: '127.0.0.1',
    fs: {
      strict: true,
      allow: ['./src', './tests'],
      deny: ['.env', '.env.*', '**/id_rsa', '**/*.pem']
    }
  }
})

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.