diff --git a/src/agents/sandbox/config.ts b/src/agents/sandbox/config.ts index 135c9a6520b..b7595ae8c4b 100644 --- a/src/agents/sandbox/config.ts +++ b/src/agents/sandbox/config.ts @@ -24,6 +24,26 @@ import type { SandboxScope, } from "./types.js"; +export const DANGEROUS_SANDBOX_DOCKER_BOOLEAN_KEYS = [ + "dangerouslyAllowReservedContainerTargets", + "dangerouslyAllowExternalBindSources", + "dangerouslyAllowContainerNamespaceJoin", +] as const; + +type DangerousSandboxDockerBooleanKey = (typeof DANGEROUS_SANDBOX_DOCKER_BOOLEAN_KEYS)[number]; +type DangerousSandboxDockerBooleans = Pick; + +function resolveDangerousSandboxDockerBooleans( + agentDocker?: Partial, + globalDocker?: Partial, +): DangerousSandboxDockerBooleans { + const resolved = {} as DangerousSandboxDockerBooleans; + for (const key of DANGEROUS_SANDBOX_DOCKER_BOOLEAN_KEYS) { + resolved[key] = agentDocker?.[key] ?? globalDocker?.[key]; + } + return resolved; +} + export function resolveSandboxBrowserDockerCreateConfig(params: { docker: SandboxDockerConfig; browser: SandboxBrowserConfig; @@ -95,15 +115,7 @@ export function resolveSandboxDockerConfig(params: { dns: agentDocker?.dns ?? globalDocker?.dns, extraHosts: agentDocker?.extraHosts ?? globalDocker?.extraHosts, binds: binds.length ? binds : undefined, - dangerouslyAllowReservedContainerTargets: - agentDocker?.dangerouslyAllowReservedContainerTargets ?? - globalDocker?.dangerouslyAllowReservedContainerTargets, - dangerouslyAllowExternalBindSources: - agentDocker?.dangerouslyAllowExternalBindSources ?? - globalDocker?.dangerouslyAllowExternalBindSources, - dangerouslyAllowContainerNamespaceJoin: - agentDocker?.dangerouslyAllowContainerNamespaceJoin ?? - globalDocker?.dangerouslyAllowContainerNamespaceJoin, + ...resolveDangerousSandboxDockerBooleans(agentDocker, globalDocker), }; } diff --git a/src/config/config.sandbox-docker.test.ts b/src/config/config.sandbox-docker.test.ts index 1124eca5fbe..138a254411d 100644 --- a/src/config/config.sandbox-docker.test.ts +++ b/src/config/config.sandbox-docker.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; import { + DANGEROUS_SANDBOX_DOCKER_BOOLEAN_KEYS, resolveSandboxBrowserConfig, resolveSandboxDockerConfig, } from "../agents/sandbox/config.js"; @@ -87,61 +88,29 @@ describe("sandbox docker config", () => { expect(res.ok).toBe(true); }); - it("uses agent override precedence for dangerouslyAllowContainerNamespaceJoin", () => { - const inherited = resolveSandboxDockerConfig({ - scope: "agent", - globalDocker: { dangerouslyAllowContainerNamespaceJoin: true }, - agentDocker: {}, - }); - expect(inherited.dangerouslyAllowContainerNamespaceJoin).toBe(true); + it("uses agent override precedence for dangerous sandbox docker booleans", () => { + for (const key of DANGEROUS_SANDBOX_DOCKER_BOOLEAN_KEYS) { + const inherited = resolveSandboxDockerConfig({ + scope: "agent", + globalDocker: { [key]: true }, + agentDocker: {}, + }); + expect(inherited[key]).toBe(true); - const overridden = resolveSandboxDockerConfig({ - scope: "agent", - globalDocker: { dangerouslyAllowContainerNamespaceJoin: true }, - agentDocker: { dangerouslyAllowContainerNamespaceJoin: false }, - }); - expect(overridden.dangerouslyAllowContainerNamespaceJoin).toBe(false); - }); + const overridden = resolveSandboxDockerConfig({ + scope: "agent", + globalDocker: { [key]: true }, + agentDocker: { [key]: false }, + }); + expect(overridden[key]).toBe(false); - it("uses agent override precedence for bind-mount dangerous overrides", () => { - const inherited = resolveSandboxDockerConfig({ - scope: "agent", - globalDocker: { - dangerouslyAllowReservedContainerTargets: true, - dangerouslyAllowExternalBindSources: true, - }, - agentDocker: {}, - }); - expect(inherited.dangerouslyAllowReservedContainerTargets).toBe(true); - expect(inherited.dangerouslyAllowExternalBindSources).toBe(true); - - const overridden = resolveSandboxDockerConfig({ - scope: "agent", - globalDocker: { - dangerouslyAllowReservedContainerTargets: true, - dangerouslyAllowExternalBindSources: true, - }, - agentDocker: { - dangerouslyAllowReservedContainerTargets: false, - dangerouslyAllowExternalBindSources: false, - }, - }); - expect(overridden.dangerouslyAllowReservedContainerTargets).toBe(false); - expect(overridden.dangerouslyAllowExternalBindSources).toBe(false); - - const sharedScope = resolveSandboxDockerConfig({ - scope: "shared", - globalDocker: { - dangerouslyAllowReservedContainerTargets: true, - dangerouslyAllowExternalBindSources: true, - }, - agentDocker: { - dangerouslyAllowReservedContainerTargets: false, - dangerouslyAllowExternalBindSources: false, - }, - }); - expect(sharedScope.dangerouslyAllowReservedContainerTargets).toBe(true); - expect(sharedScope.dangerouslyAllowExternalBindSources).toBe(true); + const sharedScope = resolveSandboxDockerConfig({ + scope: "shared", + globalDocker: { [key]: true }, + agentDocker: { [key]: false }, + }); + expect(sharedScope[key]).toBe(true); + } }); it("rejects seccomp unconfined via Zod schema validation", () => {