Skip to content

Commit 844d69d

Browse files
Merge pull request #36 from modelcontextprotocol/justin/env-var-inheritance
Inherit environment variables deemed safe by default
2 parents bfb6ffc + 08b8940 commit 844d69d

File tree

1 file changed

+48
-7
lines changed

1 file changed

+48
-7
lines changed

src/client/stdio.ts

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ChildProcess, spawn } from "node:child_process";
2+
import process from "node:process";
23
import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
34
import { JSONRPCMessage } from "../types.js";
45
import { Transport } from "../shared/transport.js";
@@ -17,11 +18,55 @@ export type StdioServerParameters = {
1718
/**
1819
* The environment to use when spawning the process.
1920
*
20-
* The environment is NOT inherited from the parent process by default.
21+
* If not specified, the result of getDefaultEnvironment() will be used.
2122
*/
22-
env?: object;
23+
env?: Record<string, string>;
2324
};
2425

26+
/**
27+
* Environment variables to inherit by default, if an environment is not explicitly given.
28+
*/
29+
export const DEFAULT_INHERITED_ENV_VARS =
30+
process.platform === "win32"
31+
? [
32+
"APPDATA",
33+
"HOMEDRIVE",
34+
"HOMEPATH",
35+
"LOCALAPPDATA",
36+
"PATH",
37+
"PROCESSOR_ARCHITECTURE",
38+
"SYSTEMDRIVE",
39+
"SYSTEMROOT",
40+
"TEMP",
41+
"USERNAME",
42+
"USERPROFILE",
43+
]
44+
: /* list inspired by the default env inheritance of sudo */
45+
["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"];
46+
47+
/**
48+
* Returns a default environment object including only environment variables deemed safe to inherit.
49+
*/
50+
export function getDefaultEnvironment(): Record<string, string> {
51+
const env: Record<string, string> = {};
52+
53+
for (const key of DEFAULT_INHERITED_ENV_VARS) {
54+
const value = process.env[key];
55+
if (value === undefined) {
56+
continue;
57+
}
58+
59+
if (value.startsWith("()")) {
60+
// Skip functions, which are a security risk.
61+
continue;
62+
}
63+
64+
env[key] = value;
65+
}
66+
67+
return env;
68+
}
69+
2570
/**
2671
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
2772
*
@@ -56,11 +101,7 @@ export class StdioClientTransport implements Transport {
56101
this._serverParams.command,
57102
this._serverParams.args ?? [],
58103
{
59-
// The parent process may have sensitive secrets in its env, so don't inherit it automatically.
60-
env:
61-
this._serverParams.env === undefined
62-
? {}
63-
: { ...this._serverParams.env },
104+
env: this._serverParams.env ?? getDefaultEnvironment(),
64105
stdio: ["pipe", "pipe", "inherit"],
65106
signal: this._abortController.signal,
66107
},

0 commit comments

Comments
 (0)