1
1
import { ChildProcess , spawn } from "node:child_process" ;
2
+ import process from "node:process" ;
2
3
import { ReadBuffer , serializeMessage } from "../shared/stdio.js" ;
3
4
import { JSONRPCMessage } from "../types.js" ;
4
5
import { Transport } from "../shared/transport.js" ;
@@ -17,11 +18,55 @@ export type StdioServerParameters = {
17
18
/**
18
19
* The environment to use when spawning the process.
19
20
*
20
- * The environment is NOT inherited from the parent process by default .
21
+ * If not specified, the result of getDefaultEnvironment() will be used .
21
22
*/
22
- env ?: object ;
23
+ env ?: Record < string , string > ;
23
24
} ;
24
25
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
+
25
70
/**
26
71
* Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout.
27
72
*
@@ -56,11 +101,7 @@ export class StdioClientTransport implements Transport {
56
101
this . _serverParams . command ,
57
102
this . _serverParams . args ?? [ ] ,
58
103
{
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 ( ) ,
64
105
stdio : [ "pipe" , "pipe" , "inherit" ] ,
65
106
signal : this . _abortController . signal ,
66
107
} ,
0 commit comments