From cb485311f0ccadb482bcda75694e423b3ede2a80 Mon Sep 17 00:00:00 2001 From: D3F4W2 Date: Wed, 29 Jul 2026 23:02:15 +0800 Subject: [PATCH] fix(cli): restrict stdio MCP environment inheritance --- .../cli/src/services/MCPService.test.ts | 34 +++++++++++++++++++ extensions/cli/src/services/mcpTransports.ts | 15 +++----- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/extensions/cli/src/services/MCPService.test.ts b/extensions/cli/src/services/MCPService.test.ts index 04b71416c73..fdd1958b095 100644 --- a/extensions/cli/src/services/MCPService.test.ts +++ b/extensions/cli/src/services/MCPService.test.ts @@ -57,6 +57,7 @@ describe("MCPService", () => { afterEach(async () => { vi.clearAllMocks(); + vi.unstubAllEnvs(); await mcpService.cleanup(); }); @@ -218,6 +219,39 @@ describe("MCPService", () => { ).resolves.not.toThrow(); }); + it("should not forward ambient environment variables to stdio servers", async () => { + vi.stubEnv("CONTINUE_MCP_TEST_SECRET", "must-not-be-inherited"); + const { StdioClientTransport } = await import( + "@modelcontextprotocol/sdk/client/stdio.js" + ); + const stdioAssistant: AssistantConfig = { + name: "stdio-assistant", + version: "1.0.0", + mcpServers: [ + { + name: "stdio-server", + command: "node", + env: { EXPLICIT_MCP_VALUE: "allowed" }, + }, + ], + } as AssistantConfig; + + await mcpService.initialize(stdioAssistant); + + expect(StdioClientTransport).toHaveBeenCalledWith( + expect.objectContaining({ + env: { EXPLICIT_MCP_VALUE: "allowed" }, + }), + ); + expect(StdioClientTransport).not.toHaveBeenCalledWith( + expect.objectContaining({ + env: expect.objectContaining({ + CONTINUE_MCP_TEST_SECRET: "must-not-be-inherited", + }), + }), + ); + }); + it("should create HttpsAgent when verifySsl is false for SSE transport", async () => { const { SSEClientTransport } = await import( "@modelcontextprotocol/sdk/client/sse.js" diff --git a/extensions/cli/src/services/mcpTransports.ts b/extensions/cli/src/services/mcpTransports.ts index 97e9440e227..6e3c8827cf3 100644 --- a/extensions/cli/src/services/mcpTransports.ts +++ b/extensions/cli/src/services/mcpTransports.ts @@ -74,19 +74,14 @@ export function constructStdioTransport( serverConfig: StdioMcpServer, connection: MCPConnectionInfo, ): StdioClientTransport { - const env: Record = serverConfig.env || {}; - if (process.env) { - for (const [key, value] of Object.entries(process.env)) { - if (!(key in env) && !!value) { - env[key] = value; - } - } - } - const transport = new StdioClientTransport({ command: serverConfig.command, args: serverConfig.args || [], - env, + // The MCP SDK adds its platform-safe default environment (for example + // PATH and HOME). Only add variables the user explicitly configured; + // forwarding process.env would expose unrelated credentials to every + // stdio MCP server. + env: serverConfig.env, cwd: serverConfig.cwd, stderr: "pipe", });