diff --git a/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts b/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts index 9b97e54ba2..f11bfe067b 100644 --- a/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts +++ b/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.test.ts @@ -83,6 +83,17 @@ describe("ACPX runtime sandbox", () => { sandbox.persistedEnvironment.PAPERCLIP_NATIVE_MCP_TOKEN, ).toBeUndefined(); expect(sandbox.persistedEnvironment.HOME).toBe(sandbox.homeDirectory); + if (agent === "codex") { + const config = await readFile( + join(sandbox.agentHomeDirectory, "config.toml"), + "utf8", + ); + expect(config).toContain("shell_snapshot = false"); + expect(config).toContain( + 'exclude = ["OPENAI_API_KEY", "CODEX_API_KEY"]', + ); + expect(config).not.toContain("provider-secret"); + } expect(await readFile(sandbox.workspaceRecordPath, "utf8")).toBe( `${fixture.binding.workspacePath}\n`, ); diff --git a/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts b/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts index 384f58544c..1bae88ec1d 100644 --- a/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts +++ b/packages/paperclip-runner/src/drivers/acpx/runtime-sandbox.ts @@ -376,6 +376,24 @@ export async function prepareAcpxRuntimeSandbox(input: { })}\n`, ); } + if (input.agent === "codex") { + await writePrivateFile( + join(agentHomeDirectory, "config.toml"), + [ + // Codex shell snapshots serialize the provider process environment. + // The ACPX sidecar receives a short-lived managed credential only so + // it can authenticate the provider; that value must never become + // durable runtime state or enter a model-invoked shell. + "[features]", + "shell_snapshot = false", + "", + "[shell_environment_policy]", + 'exclude = ["OPENAI_API_KEY", "CODEX_API_KEY"]', + "ignore_default_excludes = false", + "", + ].join("\n"), + ); + } const sanitizedSpawnInput = createSanitizedAcpxSpawnInput( input.environment,