Sites plugin MCP creates unbounded node/cmd recursion on Windows when VOLTA_HOME is not forwarded

Open 💬 1 comment Opened Jul 16, 2026 by Perfumista

What version of the IDE extension are you using?

26.707.91948 (bundled Codex CLI reports 0.144.5)

What subscription do you have?

Not included; the failure is entirely local and reproduces before any account-dependent operation.

Which IDE are you using?

VS Code 1.129.0

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64 (Windows 11 Pro)

Additional environment:

  • Bundled Sites plugin: sites@openai-bundled version 0.1.27
  • Volta: 2.0.2
  • Node managed by Volta: 24.14.0

What issue are you seeing?

The bundled Sites plugin can create an unbounded Windows process-spawning loop when Codex starts its stdio MCP server.

The plugin manifest launches a bare Node command:

{
  "mcpServers": {
    "sites-design-picker": {
      "command": "node",
      "args": ["./mcp/server.mjs"],
      "cwd": "."
    }
  }
}

On this machine, node first resolves to Volta's node.exe shim. The Codex plugin/MCP launch inherited the shim-containing PATH but did not forward VOLTA_HOME. Without VOLTA_HOME, the Volta shim resolves node back to itself through cmd.exe, producing this recursive chain:

node.exe (Volta shim)
  -> cmd.exe /C node ./mcp/server.mjs
    -> node.exe (same Volta shim)
      -> cmd.exe /C node ./mcp/server.mjs
        -> ...

The incident reached approximately 13,480 node.exe processes plus 13,484 cmd.exe processes (>27,000 total processes), caused intermittent system freezes and heavy memory compression, and made ordinary process enumeration/termination extremely slow.

The root command and working directory were confirmed as:

node ./mcp/server.mjs
<Codex plugin cache>/openai-bundled/sites/0.1.27/

The Sites server.mjs itself contains no child_process, spawn, exec, or fork calls. The recursion occurs before the real Node runtime executes the server.

What steps can reproduce the bug?

A contained Windows Job Object reproduction confirms the root cause without allowing the process tree to escape:

  1. Install Volta on Windows and place its shim directory first on PATH.
  2. Install Node through Volta (24.14.0 in this reproduction).
  3. Enable the bundled Sites plugin 0.1.27.
  4. Launch the Sites MCP command with the shim-containing PATH but with VOLTA_HOME removed:
set VOLTA_HOME=
node ./mcp/server.mjs
  1. Observe alternating Volta-shim node.exe and cmd.exe /C node ./mcp/server.mjs descendants.

Measured in a bounded Job Object after three seconds:

VOLTA_HOME present:
  stable; reaches the real Node 24.14.0 executable

VOLTA_HOME absent:
  83 active descendants after 3 seconds
  alternating node.exe (Volta shim) and cmd.exe
  never reaches the real Node executable

Direct real Node executable:
  stable MCP server process

The production incident matched the VOLTA_HOME absent chain exactly.

What is the expected behavior?

Codex should start one stable Sites MCP process using the selected real Node runtime. A malformed launcher environment must not be able to create an unbounded descendant tree.

Additional information

Suggested primary plugin fix:

{
  "mcpServers": {
    "sites-design-picker": {
      "command": "node",
      "args": ["./mcp/server.mjs"],
      "cwd": ".",
      "env_vars": ["VOLTA_HOME"]
    }
  }
}

The Codex MCP documentation already supports forwarding local environment variables via env_vars for stdio servers.

More robust alternatives/safeguards:

  1. Avoid relying on a bare tool-manager shim for a bundled local MCP server; launch through a known runtime or resolve the real executable before starting the server.
  2. Ensure plugin-provided stdio MCP servers can explicitly forward required non-secret toolchain variables such as VOLTA_HOME.
  3. On Windows, place each MCP server in a Job Object configured to kill all descendants on startup failure/timeout.
  4. Add a process-growth/startup guard so a server that does not complete MCP initialization cannot create thousands of descendants before the normal startup timeout fires.

Temporary user mitigation is disabling sites@openai-bundled or ensuring VOLTA_HOME is forwarded before the plugin MCP starts.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗