Cloud Security

Vitest RCE Chain: 53M Downloads, Three Critical Flaws

June 5, 2026 · 7 min read · By William
Vitest RCE Chain: 53M Downloads, Three Critical Flaws

Vitest RCE Flaws Target CI/CD Pipelines

Three critical remote code execution vulnerabilities in the Vitest testing framework — collectively affecting over 53 million weekly npm downloads — expose development environments and CI/CD pipelines to unauthenticated takeover. The flaws, published as GitHub Security Advisories between May 19 and June 1, 2026, chain reflected script injection, file traversal, and Chrome DevTools Protocol abuse to achieve full host compromise from a single crafted request.

Vitest, maintained by the same ecosystem as Vite, has accumulated 16,600 GitHub stars and widespread adoption across enterprise front-end and full-stack teams. If your CI pipeline runs vitest in browser mode or exposes the Vitest UI to a network interface, you are directly in the blast radius.

The Three Vulnerabilities

AdvisoryCVECVSSVectorPublished
GHSA-2h32-95rg-cpppCVE-2026-474289.8Reflected XSS → RCEMay 19, 2026
GHSA-5xrq-8626-4rwp9.8File traversal → RCEMay 19, 2026
GHSA-g8mr-85jm-7xhm9.8CDP proxy → config overwriteJun 1, 2026

All three share a common theme: the Vitest API server trusts its environment too much. When the server is exposed to a network interface — common in containerised CI runners, shared dev environments, and cloud-hosted build agents — an unauthenticated remote attacker can escalate from a single HTTP request to arbitrary Node.js code execution on the host.

Reflected Script Injection via otelCarrier

The first flaw (GHSA-2h32-95rg-cppp), credited to researcher hi-ogawa, is the most elegant of the three. Vitest’s browser mode serves a runner page at /__vitest_test__/ that embeds the otelCarrier query parameter directly into an inline <script type="module"> block without sanitisation. The vulnerable code in serverOrchestrator.ts simply inserts the raw parameter value:

otelCarrier: (alert("xss via otelCarrier"), null),

This is not a DOM-based XSS requiring complex gadget chains. It is a direct reflected injection into JavaScript source code. An attacker crafts a URL, a developer or CI process loads it, and arbitrary code runs in the Vitest server origin. Because the same page exposes window.VITEST_API_TOKEN, the injected script can recover the WebSocket authentication token and make authenticated API calls.

The confirmed proof of concept demonstrates the full chain: XSS recovers the API token → authenticated WebSocket connection writes a malicious payload into vite.config.ts → Vitest/Vite hot-reloads the config → attacker-controlled Node.js code executes. From reflected XSS to host RCE in a single page load.

File Traversal and Test Execution Abuse

The second advisory (GHSA-5xrq-8626-4rwp), also from hi-ogawa, targets the Vitest UI server. The API handler for /__vitest_attachment__ uses the deprecated isFileServingAllowed function incorrectly — it fails to pass the path through cleanUrl before the filesystem operation. On Windows, an attacker can bypass the check using path components like \\?\..\.

More critically, even on Linux, the file-serving check is irrelevant because the API exposes a saveTestFile endpoint and a rerun command. An attacker who can reach the API can write an arbitrary JavaScript file as a test and trigger its execution. The advisory states plainly: “exposing the API / Vitest UI is equivalent to giving script execution access.”

For cloud environments where Windows CI runners are common — Azure DevOps hosted agents, GitHub Actions Windows runners — the path traversal vector adds file read capability on top of code execution, potentially exfiltrating secrets, environment variables, and adjacent project files.

CDP Proxy Bypasses Security Controls

The third flaw (GHSA-g8mr-85jm-7xhm), published on June 1, 2026, by sheremet-va, undermines the very mitigations designed to address the first two. Vitest introduced allowWrite and allowExec flags to gate dangerous operations when the API is network-exposed. However, the browser mode exposes a cdp() API that forwards raw Chrome DevTools Protocol methods over the Vitest browser WebSocket RPC — and CDP is not gated by these flags.

In a verified reproduction with both allowWrite: false and allowExec: false, the researcher used CDP’s Page.setDownloadBehavior to set the browser download directory to the project root, then used Runtime.evaluate to create and download a malicious vite.config.ts. Vitest reloaded the changed config and executed the attacker’s Node.js payload. The security controls were theatre.

The runner page leaks all the metadata needed: window.VITEST_API_TOKEN, session ID, project name, and the project root path. An attacker with network access to the Vitest browser API port needs nothing else.

Why Cloud Teams Should Care

These are not theoretical desktop-only flaws. The attack surface is cloud-native:

  • CI/CD runners frequently run test suites in containerised or shared environments. A Vitest process bound to 0.0.0.0 in a container is reachable from any workload on the same network.
  • Cloud dev environments — GitHub Codespaces, Gitpod, Coder — expose Vitest ports to the internet or shared networks. An attacker who can reach the port gets RCE on the dev environment, which typically has SSH keys, cloud credentials, and repository access.
  • Supply chain pivot: a compromised CI runner can inject malicious code into the artefacts it builds, turning a test-tool vulnerability into a software supply chain incident. The recent GitHub VS Code extension breach demonstrated how developer tooling compromises cascade into corporate codebases. As IBM X-Force noted in their 2026 cloud threat analysis, large supply chain incidents have increased nearly fourfold over five years.

The assumption that “it’s just a test runner” is the vulnerability. Test frameworks run with the same privileges as the build system. In cloud CI/CD, that means cloud credentials, container registry access, and deployment keys.

Patched Versions and Immediate Actions

Vitest has released patches across multiple release lines:

  • GHSA-2h32-95rg-cppp: Upgrade to Vitest 4.1.6 or 5.0.0-beta.3 or later
  • GHSA-5xrq-8626-4rwp: Upgrade to Vitest 3.2.5 or 4.1.0 or later
  • GHSA-g8mr-85jm-7xhm: Upgrade to Vitest 3.2.5, 4.1.8, or 5.0.0-beta.4 or later

If you cannot upgrade immediately, take these steps now:

  1. Ensure Vitest never binds to a public interface. Remove any --browser.api.host=0.0.0.0 or api.host configuration.
  2. If you must expose the API, verify that allowWrite and allowExec are both false. Understand that this does not fully mitigate the CDP bypass in unpatched versions.
  3. Audit CI pipeline configurations for Vitest browser mode usage. Check vitest.config.ts, vite.config.ts, and pipeline YAML for browser-mode or UI flags.
  4. Restrict network access to Vitest ports (default 51204 for UI, 63315 for browser mode) using firewall rules or Kubernetes network policies.

The patched versions also introduce new defaults: when the API server binds to a non-localhost host, allowWrite and allowExec are automatically disabled, and the UI enters read-only mode. This is the correct default for a tool that was never designed to be network-exposed.

The Bigger Picture: Dev Tooling Trust

Vitest is not unique in assuming a trusted local environment. The same pattern recurs across the JavaScript tooling ecosystem: Vite dev servers, Webpack DevServer, Storybook, and test frameworks all ship with dangerous capabilities enabled by default because they were designed for local use. The moment these tools run in cloud environments — CI runners, dev containers, shared platforms — that trust model breaks. Organisations investing in SBOM and SLSA implementation should ensure their testing infrastructure is covered by the same controls.

As the CrowdStrike 2026 Global Threat Report documents, adversaries now move fluidly between identity, cloud, and edge environments. A test-runner RCE is not a low-severity dev tool issue — it is an initial access vector into your build pipeline, which is the most privileged system in your organisation.

Treat every development tool that listens on a port as production infrastructure. Audit it, harden it, and patch it with the same urgency you would apply to an internet-facing web server.

References