diff --git a/packages/gittensory-engine/src/miner/cli-subprocess-driver.ts b/packages/gittensory-engine/src/miner/cli-subprocess-driver.ts index 3e76eaa22..3b58edfa6 100644 --- a/packages/gittensory-engine/src/miner/cli-subprocess-driver.ts +++ b/packages/gittensory-engine/src/miner/cli-subprocess-driver.ts @@ -3,7 +3,7 @@ import type { CodingAgentDriverResult, CodingAgentDriverTask, } from "./coding-agent-driver.js"; -import { SUBPROCESS_CLI_ENV_ALLOWLIST, buildAllowlistedEnv, redactSecrets } from "../subprocess-env.js"; +import { buildAllowlistedEnv, redactSecrets } from "../subprocess-env.js"; // CLI-subprocess CodingAgentDriver (#4266). Implements the CodingAgentDriver seam (#4262) by running the coding // agent (`claude`/`codex`) as a subprocess in the attempt's scoped working directory. The spawn primitive is @@ -50,6 +50,22 @@ const DEFAULT_TIMEOUT_MS = 120_000; const MAX_TRANSCRIPT_CHARS = 8000; const MAX_ERROR_DETAIL_CHARS = 500; +const CODING_AGENT_ENV_ALLOWLIST = [ + "HTTPS_PROXY", + "HTTP_PROXY", + "LANG", + "LC_ALL", + "NODE_EXTRA_CA_CERTS", + "NO_PROXY", + "PATH", + "SSL_CERT_DIR", + "SSL_CERT_FILE", + "TERM", + "https_proxy", + "http_proxy", + "no_proxy", +] as const; + function defaultBuildArgs(task: CodingAgentDriverTask): string[] { return defaultCliSubprocessArgs(task); } @@ -77,7 +93,7 @@ export function createCliSubprocessCodingAgentDriver(options: CliSubprocessDrive const knownSecrets = options.knownSecrets ?? []; return { async run(task: CodingAgentDriverTask): Promise { - const env = buildAllowlistedEnv(options.parentEnv ?? {}, SUBPROCESS_CLI_ENV_ALLOWLIST, options.env ?? {}); + const env = buildAllowlistedEnv(options.parentEnv ?? {}, CODING_AGENT_ENV_ALLOWLIST, options.env ?? {}); const spawned = await options.spawn(options.command, buildArgs(task), { cwd: task.workingDirectory, env, diff --git a/test/unit/cli-subprocess-driver.test.ts b/test/unit/cli-subprocess-driver.test.ts index ef9c431e0..2ddebb1f5 100644 --- a/test/unit/cli-subprocess-driver.test.ts +++ b/test/unit/cli-subprocess-driver.test.ts @@ -77,20 +77,30 @@ describe("createCliSubprocessCodingAgentDriver (#4266)", () => { expect(result.error).toBe("claude_timeout_5000ms"); }); - it("hands the child a strict allowlisted env plus overlaid extras, never the full parent env", async () => { + it("hands the child a strict non-credential env plus overlaid extras, never the full parent env", async () => { const { spawn, calls } = fakeSpawn({ stdout: "", code: 0 }); const driver = createCliSubprocessCodingAgentDriver({ command: "claude", spawn, - parentEnv: { HOME: "/home/miner", RUNTIME_ONLY_FLAG: "leak-me", PATH: "/usr/bin" }, - env: { AGENT_SESSION_HANDLE: "provided-by-caller" }, + parentEnv: { + HOME: "/home/miner", + RUNTIME_ONLY_FLAG: "leak-me", + PATH: "/usr/bin", + XDG_CONFIG_HOME: "/home/miner/.config", + XDG_DATA_HOME: "/home/miner/.local/share", + XDG_STATE_HOME: "/home/miner/.local/state", + }, + env: { AGENT_SESSION_HANDLE: "provided-by-caller", HOME: "/tmp/isolated-agent-home" }, }); await driver.run(TASK); const env = calls[0]?.opts.env ?? {}; - expect(env.HOME).toBe("/home/miner"); + expect(env.HOME).toBe("/tmp/isolated-agent-home"); expect(env.PATH).toBe("/usr/bin"); expect(env.AGENT_SESSION_HANDLE).toBe("provided-by-caller"); expect(env.RUNTIME_ONLY_FLAG).toBeUndefined(); + expect(env.XDG_CONFIG_HOME).toBeUndefined(); + expect(env.XDG_DATA_HOME).toBeUndefined(); + expect(env.XDG_STATE_HOME).toBeUndefined(); }); it("redacts known secret values and honors a custom argv builder", async () => {