Files
deepseek-harness/packages/sandbox
kingwl 669771097d subagent: inherit parent sandbox/approval overrides in in-process children
Per-session policy overrides (sandbox/mode, approval/policy) never crossed
the delegation boundary: a spawn child of a read-only-switched parent ran
under the wider deployment default, and a fork child missed any switch made
after its seed boundary — delegation was a bypass channel for a user's
tightening.

The in-process driver now snapshots the delegating parent's override chain
and stamps it onto the child through the canonical write paths
(SandboxPolicyService.inheritOverride / ApprovalService.inheritOverride),
anchored inside the child's first turn via a one-shot agent/prompt-submit
listener: turn-enclosed (durable), ahead of the first request (an inherited
'never' reaches the child's first system prompt), and positioned after any
stale fork-seed switch so the ordinary last-event-wins fold resolves it.
Only overrides are copied — an unswitched parent stamps nothing and the
child follows the live deployment default; both services are consumed
opportunistically, so compositions without them delegate unchanged. Nesting
composes by construction (each stamp folds the already-stamped parent log).

Evidence: inheritance.spec.ts drives scripted-model children into the real
dsh-fs-sandbox fence through the real write tool (disk-state + denial-marker
assertions; spawn, stale-seed fork, grandchild, escalation fail-closed, and
no-stamp guards), inheritOverride contract tests in both service suites, and
the recorded subagent-sandbox-inheritance ACP snapshot (read-only preset →
delegate → child denied, replayed keylessly).

See .agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md.
2026-07-25 04:06:19 +08:00
..

sandbox/ — process-sandbox capability family

The confinement half of the capability-seam split: an abstract provider interface, platform backends, and the shared policy home. Consumers hand ctx.sandbox the exact argv they are about to spawn and spawn the returned (wrapped) argv instead; a complete SandboxExecutionPolicy (mode + workspace root) rides each capability call, and its confined subset becomes the provider's SandboxPolicy. Different sessions and consumers can therefore confine under different policies at the same instant. All product packages.

Package Role ctx key
sandbox/ Abstract process-sandbox seam (the SandboxProvider contract + the mode/enforcement/policy vocabulary) plus the shared ESCALATION kit (approveEscalation, the strictly-wider ladder, the denial/hint markers) and the writableRoots derivation every enforcement dialect shares ctx.sandbox
sandbox-local/ Local backends by platform chain: Linux bwrap else the landlock-run launcher (the npm-distributed node-addon-landlock-run family, built and released from its own repository), darwin sandbox-exec/Seatbelt — multi-candidate chains functionally probed, sole candidates selected directly, verdict cached, fail-closed (registers ctx.sandbox)
sandbox-policy/ The policy resolver: deployment fallbacks plus each session's durable mode and immutable cwd root. Both enforcing families consume its complete per-call result, so bash and fs cannot confine to different roots ctx.sandboxPolicy

The seam confines SAME-WORLD subprocesses only (shared filesystem and kernel). Containers, microVMs, and remote executors are NOT backends here — they replace whole capability implementations (ctx.bash, ctx.fs) as environment-coherent groups; the boundary is recorded in the sandbox Agent Note.

Consumers today: bash/bash-sandbox (wraps ['bash', '-c', command] through ctx.sandbox) and fs/fs-sandbox (an in-process path fence, not an argv wrapper — reads ctx.sandboxPolicy and enforces the shared mode on write/edit). The cross-family boundary is the sandbox Agent Note's cross-family fs sandbox phase; the shared vocabulary lets both families teach the model one denial marker and one escalation flow.