From 3447575417b35b2c92878aea58fa89d95df95957 Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Tue, 5 Nov 2024 11:56:15 +0000 Subject: [PATCH 1/2] Inherit environment variables deemed safe by default --- src/client/stdio.ts | 61 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/src/client/stdio.ts b/src/client/stdio.ts index 98f5b77f..9f1301d4 100644 --- a/src/client/stdio.ts +++ b/src/client/stdio.ts @@ -1,4 +1,5 @@ import { ChildProcess, spawn } from "node:child_process"; +import process from "node:process"; import { ReadBuffer, serializeMessage } from "../shared/stdio.js"; import { JSONRPCMessage } from "../types.js"; import { Transport } from "../shared/transport.js"; @@ -17,11 +18,61 @@ export type StdioServerParameters = { /** * The environment to use when spawning the process. * - * The environment is NOT inherited from the parent process by default. + * If not specified, the result of getDefaultEnvironment() will be used. */ - env?: object; + env?: Record; }; +/** + * Environment variables to inherit by default, if an environment is not explicitly given. + */ +export const DEFAULT_INHERITED_ENV_VARS = + process.platform === "win32" + ? [ + "ALLUSERSPROFILE", + "APPDATA", + "HOMEDRIVE", + "HOMEPATH", + "LOCALAPPDATA", + "NUMBER_OF_PROCESSORS", + "OS", + "PATH", + "PATHEXT", + "PROCESSOR_ARCHITECTURE", + "SYSTEMDRIVE", + "SYSTEMROOT", + "TEMP", + "TMP", + "USERNAME", + "USERPROFILE", + "WINDIR", + ] + : /* list inspired by the default env inheritance of sudo */ + ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"]; + +/** + * Returns a default environment object including only environment variables deemed safe to inherit. + */ +export function getDefaultEnvironment(): Record { + const env: Record = {}; + + for (const key of DEFAULT_INHERITED_ENV_VARS) { + const value = process.env[key]; + if (value === undefined) { + continue; + } + + if (value.startsWith("()")) { + // Skip functions, which are a security risk. + continue; + } + + env[key] = value; + } + + return env; +} + /** * Client transport for stdio: this will connect to a server by spawning a process and communicating with it over stdin/stdout. * @@ -56,11 +107,7 @@ export class StdioClientTransport implements Transport { this._serverParams.command, this._serverParams.args ?? [], { - // The parent process may have sensitive secrets in its env, so don't inherit it automatically. - env: - this._serverParams.env === undefined - ? {} - : { ...this._serverParams.env }, + env: this._serverParams.env ?? getDefaultEnvironment(), stdio: ["pipe", "pipe", "inherit"], signal: this._abortController.signal, }, From 08b89404a38977f7e3878f1bee9498831addc884 Mon Sep 17 00:00:00 2001 From: Justin Spahr-Summers Date: Tue, 5 Nov 2024 12:10:24 +0000 Subject: [PATCH 2/2] Trim Windows list down based on review --- src/client/stdio.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/client/stdio.ts b/src/client/stdio.ts index 9f1301d4..93b2550e 100644 --- a/src/client/stdio.ts +++ b/src/client/stdio.ts @@ -29,23 +29,17 @@ export type StdioServerParameters = { export const DEFAULT_INHERITED_ENV_VARS = process.platform === "win32" ? [ - "ALLUSERSPROFILE", "APPDATA", "HOMEDRIVE", "HOMEPATH", "LOCALAPPDATA", - "NUMBER_OF_PROCESSORS", - "OS", "PATH", - "PATHEXT", "PROCESSOR_ARCHITECTURE", "SYSTEMDRIVE", "SYSTEMROOT", "TEMP", - "TMP", "USERNAME", "USERPROFILE", - "WINDIR", ] : /* list inspired by the default env inheritance of sudo */ ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"];