From e7219b3ab778cdd04be467e995ed6be9e0e0f52e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:24:40 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20Fix=20e?= =?UTF-8?q?xeca=20framework=20secrets=20leakage=20via=20extendEnv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly set `extendEnv: false` and explicitly pass the merged sanitized environment everywhere `execa` is used across the codebase, particularly in the core CLI capabilities and tool auth boundaries. This fixes a high-priority risk where unmodified process.env would be implicitly injected. --- src/cli/authorization/non-interactive.ts | 3 +++ src/core/tools/capability/runner.ts | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cli/authorization/non-interactive.ts b/src/cli/authorization/non-interactive.ts index 369e269b..d390a89c 100644 --- a/src/cli/authorization/non-interactive.ts +++ b/src/cli/authorization/non-interactive.ts @@ -1,6 +1,7 @@ import { execa } from 'execa'; import { z } from 'zod'; +import { sanitizeEnvironment } from '../../core/utils/sanitizer.js'; import type { AuthorizationDecision, ResolvedExtensions, @@ -101,6 +102,8 @@ export async function requestNonInteractiveAuthorizationDecision(params: { shell: true, timeout: timeoutMs, reject: false, + env: sanitizeEnvironment(process.env), + extendEnv: false, }); if (typeof res.exitCode === 'number' && res.exitCode !== 0) { diff --git a/src/core/tools/capability/runner.ts b/src/core/tools/capability/runner.ts index dbba2080..d2e20ba2 100644 --- a/src/core/tools/capability/runner.ts +++ b/src/core/tools/capability/runner.ts @@ -1,5 +1,6 @@ import { execa } from 'execa'; +import { sanitizeEnvironment } from '../../utils/sanitizer.js'; import { ExecOpts, ExecResult } from './types.js'; /** @@ -15,7 +16,8 @@ export function createControlledRunner() { cwd: opts?.cwd, timeout: opts?.timeoutMs, maxBuffer: opts?.maxStdoutBytes, - env: opts?.env, + env: sanitizeEnvironment(opts?.env ? { ...process.env, ...opts.env } : process.env), + extendEnv: false, reject: false, // Backends should handle exit codes themselves }); From 35e3c0e0b32b5cdf73f9d033dcdaa0b8fe2e5e60 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:29:47 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20Fix=20e?= =?UTF-8?q?xeca=20framework=20secrets=20leakage=20via=20extendEnv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly set `extendEnv: false` and explicitly pass the merged sanitized environment everywhere `execa` is used across the codebase, particularly in the core CLI capabilities and tool auth boundaries. This fixes a high-priority risk where unmodified process.env would be implicitly injected. Fixes ESLint import order errors preventing CI from passing. --- src/cli/authorization/non-interactive.ts | 2 +- src/core/tools/capability/runner.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cli/authorization/non-interactive.ts b/src/cli/authorization/non-interactive.ts index d390a89c..c67182f1 100644 --- a/src/cli/authorization/non-interactive.ts +++ b/src/cli/authorization/non-interactive.ts @@ -1,7 +1,6 @@ import { execa } from 'execa'; import { z } from 'zod'; -import { sanitizeEnvironment } from '../../core/utils/sanitizer.js'; import type { AuthorizationDecision, ResolvedExtensions, @@ -14,6 +13,7 @@ import { McpConnectionManager, } from '../../core/facades/cli-authorization-non-interactive.js'; import { isRecord } from '../../core/facades/cli-utils-serialize.js'; +import { sanitizeEnvironment } from '../../core/utils/sanitizer.js'; import { text } from '../locales/index.js'; const DecisionSchema = z diff --git a/src/core/tools/capability/runner.ts b/src/core/tools/capability/runner.ts index d2e20ba2..91c71c9d 100644 --- a/src/core/tools/capability/runner.ts +++ b/src/core/tools/capability/runner.ts @@ -1,6 +1,7 @@ import { execa } from 'execa'; import { sanitizeEnvironment } from '../../utils/sanitizer.js'; + import { ExecOpts, ExecResult } from './types.js'; /** From 6e72fb856b8c6234c6ad16ead84dbd566dcdadfa Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:53:56 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20Fix=20e?= =?UTF-8?q?xeca=20framework=20secrets=20leakage=20via=20extendEnv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly set `extendEnv: false` and explicitly pass the merged sanitized environment everywhere `execa` is used across the codebase, particularly in the core CLI capabilities and tool auth boundaries. This fixes a high-priority risk where unmodified process.env would be implicitly injected. Fixes ESLint import order errors preventing CI from passing by applying facade exports appropriately. --- src/cli/authorization/non-interactive.ts | 2 +- src/core/facades/cli-authorization-non-interactive.ts | 2 ++ src/core/tools/capability/runner.ts | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cli/authorization/non-interactive.ts b/src/cli/authorization/non-interactive.ts index c67182f1..9800a5bd 100644 --- a/src/cli/authorization/non-interactive.ts +++ b/src/cli/authorization/non-interactive.ts @@ -11,9 +11,9 @@ import type { import { getLogger, McpConnectionManager, + sanitizeEnvironment, } from '../../core/facades/cli-authorization-non-interactive.js'; import { isRecord } from '../../core/facades/cli-utils-serialize.js'; -import { sanitizeEnvironment } from '../../core/utils/sanitizer.js'; import { text } from '../locales/index.js'; const DecisionSchema = z diff --git a/src/core/facades/cli-authorization-non-interactive.ts b/src/core/facades/cli-authorization-non-interactive.ts index 63dd39f2..a3ce4040 100644 --- a/src/core/facades/cli-authorization-non-interactive.ts +++ b/src/core/facades/cli-authorization-non-interactive.ts @@ -6,3 +6,5 @@ export type { AuthorizationDecision, ToolAuthorizationRequest, } from '../tools/authorization/types.js'; + +export { sanitizeEnvironment } from '../utils/sanitizer.js'; diff --git a/src/core/tools/capability/runner.ts b/src/core/tools/capability/runner.ts index 91c71c9d..d2e20ba2 100644 --- a/src/core/tools/capability/runner.ts +++ b/src/core/tools/capability/runner.ts @@ -1,7 +1,6 @@ import { execa } from 'execa'; import { sanitizeEnvironment } from '../../utils/sanitizer.js'; - import { ExecOpts, ExecResult } from './types.js'; /**