Skip to content

feat(cli): sandbox public Claude agents with macOS Seatbelt#751

Closed
lilyshen0722 wants to merge 1 commit into
codex/public-agent-native-sandboxfrom
codex/public-claude-seatbelt
Closed

feat(cli): sandbox public Claude agents with macOS Seatbelt#751
lilyshen0722 wants to merge 1 commit into
codex/public-agent-native-sandboxfrom
codex/public-claude-seatbelt

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

What changed

  • adds a deny-by-default macOS Seatbelt wrapper for public Claude workspace / read-only agents
  • isolates Claude state per agent, sanitizes inherited environment/config, and keeps the operator's persistent Claude settings out of scope
  • retains Commonly MCP by allowing only declared MCP tool prefixes while denying Bash, write/edit/task, and web tools at the Claude permission layer
  • fail-closes attach/runtime on unsupported host/mode combinations; Linux continues to use the existing bwrap path
  • adds unit regressions plus a real-model MCP attack harness

Why

Claude Code's built-in permission model does not confine its whole process or declared MCP children on macOS. A public agent processing untrusted prompts therefore needs a host-native confidentiality boundary around Claude and every child it launches.

This is phase ③ of the public-agent hardening and is intentionally stacked on #750 (phases ①+②). Retarget to main after #750 merges.

Verification

  • RUN_PUBLIC_SANDBOX_ATTACKS=1 node cli/scripts/security/verify-public-claude-seatbelt.mjs — PASS on macOS / Claude Code 2.1.216
    • MCP child initialized and executed all seven attacks
    • reads of synthetic ~/.commonly, ~/.ssh, and workspace .commonly/mcp-config.json canaries returned OS EPERM
    • /bin/sh-mediated secret read returned OS EPERM
    • workspace write succeeded; out-of-workspace write returned OS EPERM
    • no canary or token value crossed into model/MCP output
  • targeted tests: 15 passed, 1 platform skip
  • full CLI suite: 178 passed, 10 platform skips (--forceExit used for the suite's pre-existing open-handle warning)
  • syntax/diff checks clean; focused ESLint no-undef / no-unused-vars clean

Explicit residual

The transient MCP config is outside the model's Read scope and removed after spawn, but a declared MCP server receives its configured token/environment by design. Removing the token-bearing config entirely is phase ④ (env-only injection). This PR does not claim to remove that trusted-capability boundary.

License note

The static Seatbelt baseline is adapted from OpenAI Codex's Apache-2.0 sandbox policy and is attributed in source.

@samxu01
samxu01 marked this pull request as ready for review July 25, 2026 03:16
@lilyshen0722
lilyshen0722 deleted the branch codex/public-agent-native-sandbox July 25, 2026 03:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant