Security: enforce ACP sandbox inheritance for sessions_spawn (#32254)

* Security: enforce ACP sandbox inheritance in sessions_spawn

* fix: add changelog attribution for ACP sandbox inheritance (#32254) (thanks @dutifulbob)

---------

Co-authored-by: Onur <2453968+osolmaz@users.noreply.github.com>
This commit is contained in:
Bob
2026-03-02 23:50:38 +01:00
committed by GitHub
parent a78ec81ae6
commit ac11f0af73
8 changed files with 124 additions and 2 deletions

View File

@@ -32,9 +32,12 @@ import {
} from "../infra/outbound/session-binding-service.js";
import { normalizeAgentId } from "../routing/session-key.js";
import { normalizeDeliveryContext } from "../utils/delivery-context.js";
import { resolveSandboxRuntimeStatus } from "./sandbox/runtime-status.js";
export const ACP_SPAWN_MODES = ["run", "session"] as const;
export type SpawnAcpMode = (typeof ACP_SPAWN_MODES)[number];
export const ACP_SPAWN_SANDBOX_MODES = ["inherit", "require"] as const;
export type SpawnAcpSandboxMode = (typeof ACP_SPAWN_SANDBOX_MODES)[number];
export type SpawnAcpParams = {
task: string;
@@ -43,6 +46,7 @@ export type SpawnAcpParams = {
cwd?: string;
mode?: SpawnAcpMode;
thread?: boolean;
sandbox?: SpawnAcpSandboxMode;
};
export type SpawnAcpContext = {
@@ -51,6 +55,7 @@ export type SpawnAcpContext = {
agentAccountId?: string;
agentTo?: string;
agentThreadId?: string | number;
sandboxed?: boolean;
};
export type SpawnAcpResult = {
@@ -228,6 +233,26 @@ export async function spawnAcpDirect(
error: "ACP is disabled by policy (`acp.enabled=false`).",
};
}
const sandboxMode = params.sandbox === "require" ? "require" : "inherit";
const requesterRuntime = resolveSandboxRuntimeStatus({
cfg,
sessionKey: ctx.agentSessionKey,
});
const requesterSandboxed = ctx.sandboxed === true || requesterRuntime.sandboxed;
if (requesterSandboxed) {
return {
status: "forbidden",
error:
'Sandboxed sessions cannot spawn ACP sessions because runtime="acp" runs on the host. Use runtime="subagent" from sandboxed sessions.',
};
}
if (sandboxMode === "require") {
return {
status: "forbidden",
error:
'sessions_spawn sandbox="require" is unsupported for runtime="acp" because ACP sessions run outside the sandbox. Use runtime="subagent" or sandbox="inherit".',
};
}
const requestThreadBinding = params.thread === true;
const spawnMode = resolveSpawnMode({