Skip to content

feat(shell): opt-in os sandboxing via sandbox-runtime - #1428

Merged
TheGreatAxios merged 1 commit into
mainfrom
cl-10663-shell-sandboxing-adopt-sandbox-runtime-opt-in-fail-closed
Oct 15, 2026
Merged

TheGreatAxios merged 1 commit into
mainfrom
cl-10663-shell-sandboxing-adopt-sandbox-runtime-opt-in-fail-closed

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • Adds opt-in OS-level shell sandboxing via @anthropic-ai/sandbox-runtime (pinned exact; scoped package — the unscoped npm name is a documented squatter). When shell.sandbox.enabled is set (global settings only, default OFF), every model-reachable child-process seam is wrapped: run_shell (shell-guard plugin), background run_shell, MCP stdio server spawns, and lifecycle-hook spawn — the hook discovery directory lives inside the model-writable session root, so its spawn is wrapped too, keeping a planted hook from executing outside the OS sandbox in a later session.
  • Config is derived from the session root, the secret-guard deny list, and the permission tiers; filesystem writes are allow-only to the session root + tmpdirs, reads are deny-based; unconfirmed network hosts route through the real approval gate as a synthetic ask (non-interactive sessions deny, never silently allow). Yolo mode removes asks only — the OS sandbox stays on.
  • Disabled means byte-identical spawn passthrough (field-pinned, env included). Enabled-but-unavailable fails closed at every seam with an error and never raw-spawns; the process-global sandbox manager is singleflight/refcounted so a conflicting second composition fails loud and teardown can never leave a config-less wrap path (regression tests for both).
  • Out of scope, noted: Windows (srt alpha), Linux host validation (needs bubblewrap/socat/ripgrep — spike-verified mechanics, runtime validation pending), sandbox-exec is deprecated-but-functional upstream (long-term risk named in the ticket).

Verification

  • Spike (recorded on CL-10663): Bun 1.4.2 macOS Seatbelt verified empirically — fs denies incl. symlink alias, network proxy ask/allow paths, fail-closed on missing dependencies, hardcoded absolute sandbox-exec resists PATH spoofing.
  • Warden trust review (two rounds): fail-closed seams, yolo non-bypass, settings-authorship (global-only resolution; local settings allowlist rejects the key; model writes hard-denied by secret-guard), supply-chain pin + integrity all verified. Two escape-hatch findings from round 1 (hook-discovery spawn; process-global manager races) are fixed in this commit with regression tests.
  • bun run check exit 0: 8964 pass / 0 fail; targeted suites: shell-guard-plugin 45, shell-guard-sandbox 8, background-shell 7, sandbox-config 13, hooks-sandbox (new) all green.
  • Known lockfile note: @intx/* dedupe re-keying from bun's re-resolve on any dependency change is deterministic (tracked in CL-10681).

Fixes CL-10663

Model-driven child processes now pass through an os-level sandbox
wrapper when shell.sandbox.enabled is set (Seatbelt on macOS,
bubblewrap+netns on Linux). The wrapper builds its config from the
session root, the secret-guard deny list and the permission tiers; a
network ask callback routes unconfirmed hosts through the approval
gate. Disabled means byte-identical spawn passthrough; enabled-but-
unavailable fails closed with an error, never a raw spawn. The os
sandbox stays on in yolo mode, which only removes asks. The runtime is
pinned exact (scoped package) so beta releases cannot float in.

Windows support is alpha upstream and left unwrapped; hosts type
config. hooks.ts spawn stays outside the wrapped seams for now.
@linear-code

linear-code Bot commented Oct 14, 2026

Copy link
Copy Markdown

CL-10663

@corbits-triage

corbits-triage Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Superseded by the comment below.

@corbits-triage

Copy link
Copy Markdown
Contributor

This supersedes the comment above because the rules changed: repository policy version 4 → version 16.

Triage: Fail

@TheGreatAxios, please address the following:

  • does not meet "this is bug free?"

Not yet confirmed, a maintainer will check:

  • meets "t"

@TheGreatAxios
TheGreatAxios merged commit ede628b into main Oct 15, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant