fix: isolate stdio MCP child env from OpenWiki credentials#287
Open
Greg Land (bikeusaland) wants to merge 4 commits into
Open
fix: isolate stdio MCP child env from OpenWiki credentials#287Greg Land (bikeusaland) wants to merge 4 commits into
Greg Land (bikeusaland) wants to merge 4 commits into
Conversation
Stdio MCP subprocesses were spawned with the full process.env, so any MCP server command (which comes from user-editable connector config) inherited every provider API key and OAuth refresh token. Build the child env from an allow-list of safe base variables (PATH, HOME, TMPDIR, locale/terminal, Windows equivalents) plus only the credentials the transport explicitly declares via transport.env. The full process.env is never forwarded. Route all three stdio spawn sites through the new buildChildEnv helper. Add test/mcp-client.test.ts pinning the invariant: secrets don't leak by key or value, allow-listed base vars pass through, declared refs resolve to the mapped target var, and invalid/unresolvable refs throw. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 12, 2026
audichuang
added a commit
to audichuang/openwiki
that referenced
this pull request
Jul 15, 2026
…angchain-ai#287) Spawned stdio MCP servers inherited the full process.env — every provider API key and OAuth refresh token. Build the child env from a small allowlist of safe base vars (PATH/HOME/tmp/locale/Windows) plus only the credentials the transport declares via transport.env. Ported from upstream PR langchain-ai#287 (clean, engine-agnostic; our tree did not touch mcp-client.ts). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
audichuang
added a commit
to audichuang/openwiki
that referenced
this pull request
Jul 16, 2026
…angchain-ai#287) Spawned stdio MCP servers inherited the full process.env — every provider API key and OAuth refresh token. Build the child env from a small allowlist of safe base vars (PATH/HOME/tmp/locale/Windows) plus only the credentials the transport declares via transport.env. Ported from upstream PR langchain-ai#287 (clean, engine-agnostic; our tree did not touch mcp-client.ts). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Stdio MCP subprocesses were spawned with the full
process.env:Because the MCP server command comes from user-editable connector config, any MCP server binary inherited the user's entire credential set — every provider API key (Anthropic, OpenAI, Tavily, …) and OAuth refresh token (Gmail, Slack, X, …) sitting in
process.env. A malicious or compromised MCP server got all of them for free.Fix
Introduce
buildChildEnv, which constructs the child environment from:PATH,HOME/USERPROFILE,TMPDIR/TEMP/TMP, locale/terminal vars, and Windows equivalents (SystemRoot,ComSpec,PATHEXT).transport.env(resolved through the existingresolveChildEnvvalidation/resolution path).The full
process.envis never forwarded. All three stdio spawn sites (executeStdioMcp,executeStdioMcpTool,listStdioMcpTools) now route throughbuildChildEnv.Behavior change
If an MCP server previously relied on a variable that is neither allow-listed nor declared in its
transport.env, it will no longer see it — that variable must now be listed explicitly in the connector'stransport.env. This is the intended least-privilege behavior.Tests
Adds
test/mcp-client.test.ts(the module had no tests) pinning the invariant:PATH) pass throughFull gate passes locally:
typecheck,lint:check,format:check, and the test suite (200 tests, +5 new).🤖 Generated with Claude Code
Related PRs
Part of a batch from a single codebase-review pass. Independent,
main-based branches that can merge in any order.Security
Correctness
Feature
(This PR is #287.)