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