11import { ChildProcess, spawn } from "node:child_process";
2+ import process from "node:process";
23import { ReadBuffer, serializeMessage } from "../shared/stdio.js";
34import { JSONRPCMessage } from "../types.js";
45import { Transport } from "../shared/transport.js";
@@ -17,11 +18,61 @@ 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+ "ALLUSERSPROFILE",
33+ "APPDATA",
34+ "HOMEDRIVE",
35+ "HOMEPATH",
36+ "LOCALAPPDATA",
37+ "NUMBER_OF_PROCESSORS",
38+ "OS",
39+ "PATH",
40+ "PATHEXT",
41+ "PROCESSOR_ARCHITECTURE",
42+ "SYSTEMDRIVE",
43+ "SYSTEMROOT",
44+ "TEMP",
45+ "TMP",
46+ "USERNAME",
47+ "USERPROFILE",
48+ "WINDIR",
49+ ]
50+ : /* list inspired by the default env inheritance of sudo */
51+ ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"];
52+
53+ /**
54+ * Returns a default environment object including only environment variables deemed safe to inherit.
55+ */
56+ export function getDefaultEnvironment(): Record<string, string> {
57+ const env: Record<string, string> = {};
58+
59+ for (const key of DEFAULT_INHERITED_ENV_VARS) {
60+ const value = process.env[key];
61+ if (value === undefined) {
62+ continue;
63+ }
64+
65+ if (value.startsWith("()")) {
66+ // Skip functions, which are a security risk.
67+ continue;
68+ }
69+
70+ env[key] = value;
71+ }
72+
73+ return env;
74+ }
75+
2576/**
2677 * Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
2778 *
@@ -56,11 +107,7 @@ export class StdioClientTransport implements Transport {
56107 this._serverParams.command,
57108 this._serverParams.args ?? [],
58109 {
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 },
110+ env: this._serverParams.env ?? getDefaultEnvironment(),
64111 stdio: ["pipe", "pipe", "inherit"],
65112 signal: this._abortController.signal,
66113 },
0 commit comments