medium

CVE-2026-84373

npm · @vitest/mocker

Summary

Vitest: Path Traversal / Arbitrary File Read via @vitest/mocker Redirect Mock

Severity
medium
CVSS
5.9
EPSS
0.4% (p31)
CWE
CWE-22
Also known as
GHSA-82fw-gwwq-j7x9#@vitest/mocker
Published
2026-09-08
Updated
2026-09-08

Advisory details

Summary

@vitest/mocker registers a redirect mock's target path without validating it against the dev server's file-serving allowlist. An attacker who can reach the dev server's WebSocket can register a redirect mock pointing outside the project root; when the mocked module is requested, the plugin's load hook returns readFile(<attacker path>) as the module source, disclosing local files.

This is exploitable without authentication only through the public mockerPlugin / standalone interceptorPlugin exports (used by third-party dev servers), which register the handler on Vite's unauthenticated HMR socket. Vitest's own browser mode registers mocks over a token-authenticated RPC and is not remotely reachable by default (see Scope).

Affected code

packages/mocker/src/node/interceptorPlugin.ts.

The load hook is the file-read sink:

if (mock.type === 'redirect') {
  return readFile(mock.redirect, 'utf-8')
}

mock.redirect is derived from client input at registration time with no boundary check:

if (event.type === 'redirect') {
  const redirectUrl = new URL(event.redirect)
  event.redirect = join(server.config.root, redirectUrl.pathname)
}
registry.register(event)

There is no server.fs.allow / server.fs.deny check and no assertion that the resolved path stays within the project root.

Registration paths and trust boundaries

Path handling

new URL(redirect).pathname combined with join(root, pathname) does not confine reads to the root:

Even without escaping the root, the missing server.fs check allows reading any in-root file the dev server would otherwise refuse to serve (for example an in-root .env or source that is denied by server.fs.deny).

Scope / preconditions

Impact

Disclosure of local files readable by the dev-server process (source, in-root .env/secrets, and, via the opaque-scheme payload, files outside the project root). No integrity or availability impact.

Affected versions

Present since @vitest/mocker was introduced.

Fix

Validate the resolved redirect target against Vite's file-serving allowlist (isFileLoadingAllowed) before registering it, at every registration site, and stop registering the interceptor WebSocket events in Vitest's browser mode (mocks there flow through the authenticated RPC).

References

Related advisories

Is your project exposed to this? Stateward checks every dependency on every pull request and flags it only if your code actually reaches it.

Check my repo

Summarize with AI

ChatGPTClaudePerplexity

Sources: CISA KEV (public domain), OSV.dev & GitHub Advisory Database (CC-BY-4.0), FIRST EPSS, NVD/CWE (public domain). Served live from the Stateward advisory database.