Repository navigation
Sonny: sandbox leads and tasks by default - #285
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
… a process slot, a child's roots keep what its creator's keep read-only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
… pass on no root the creator keeps read-only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…s; children inherit the sandbox without ceilings; take placeholders before a process slot Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…amed or linked; each Seatbelt rule names only its own paths, once Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
… the socket Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…-6zwinw # Conflicts: # docs/DAEMON_MEASUREMENTS.md
…apped to what it may do Each sandboxed bot gets a socket of its own beside the daemon's, bound over the daemon's path in bwrap and allowed by Seatbelt, and named by AGENT_SOCKET, so the agent CLI works in its shell. Requests on it answer as that bot: no configure, answers, tool results, serving approvals or shutdown; what it makes is its own and inherits its sandbox inside its folders; it removes only its own bots; what it sends reads as its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
… only the answered tools its maker passes on Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…to claude/project-thread-6zwinw # Conflicts: # docs/RUST_PROTOTYPE.md # src/sandbox.rs # src/server/mod.rs # src/server/turn.rs # src/tools.rs # tests/test_approvals.py # tests/tool_contract.rs
The test's own socket sat beside the daemon's, so hiding the folder of bots' sockets hid the daemon's path too; the daemon keeps them in SOCKET.d/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
A folder a bot was given can sit in one its creator may write, and the creator can swap a link in for it later; bound by its path, bubblewrap would follow that link. Each root is now opened folder by folder without following links, refused if one was swapped in, and bound from that descriptor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…lose a bot's socket with it A fork keeps its source's declared tools, so forking a bot whose tools a client answers is held to what the caller may pass on, as create is. A turn's folder becomes the bot's, so one given to any sandboxed bot must be the caller's to write. A deleted or expired bot's own socket is closed and removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
… sockets off the runtime thread Pinned descriptors outlived bubblewrap into the command itself, which could reach the host's folders through them. Each confined call builds its policy anew, off the runtime thread, so a root that a link was swapped in for since is refused there instead. Closing a deleted bot's own socket takes a lock and unlinks a file, so it runs on a blocking worker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…-6zwinw # Conflicts: # docs/DAEMON_MEASUREMENTS.md
…-6zwinw # Conflicts: # docs/DAEMON_MEASUREMENTS.md
…rred attribution stable across retries A caller whose allowed list leaves out a client-answered tool can't declare it for a bot it makes, nor have a new bot inherit it. A submit on a bot's own socket without from is named by the caller's name as origin, never by whatever turn it runs then, so a retry is the same request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…ts source's allowed list Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…-6zwinw # Conflicts: # docs/DAEMON_MEASUREMENTS.md
The store answers a resent fork before it looks up the source, so a client recovering a lost response still gets the fork it made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
…ndbox A lead in auto or ask mode is made, or set again when Sonny opens it, with Codex's workspace-write sandbox, the network on and its repository's git folder writable, so a commit doesn't ask. In full mode it runs unconfined. Every task is confined the same way in its own folder, whatever its lead's mode. The daemon's configure takes sandbox, writable and network, held no weaker than the creator's for a bot another bot made. A git folder given as a writable folder keeps its hooks and config read-only, as .git is kept, and its missing hooks may not be made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (2)
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex review Generated by Claude Code |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e860f68ed9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: e860f68ed9
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
… keep per-worktree-config git folders read-only A project's lead is created with its sandbox, so a host that can't make one refuses the lead rather than running it unconfined until configure. A lead whose writable folders no longer match its folder's repository, as after the folder moves, takes the sandbox again. A git folder whose config turns on per-worktree config, or a repository's whose config is missing, stays read-only as a whole: git reads those files wherever they are made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa39c8b6b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A bot that may write the folder could rename HEAD for one call and the next would build its sandbox without the hooks kept. The name, .git or NAME.git, is the settings' and the bot can't change it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a59e69226b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A separate git folder named otherwise isn't known to the daemon as git's, so its hooks and config wouldn't be kept; commits there ask instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2115930af
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…nd submodules' git folders read-only A lead new_project makes is created with the auto gate as well as the sandbox, so opening it doesn't read it as full and unconfine it; and Sonny only ever confines a lead on opening it, never unconfines. A git folder whose config includes other files stays read-only as a whole, and its modules folder, which holds submodules' hooks and config, stays read-only within it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a375dc932b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A bot could make .git/commondir point at a folder of its own, so git outside the sandbox ran that folder's hooks and config. commondir is now kept like hooks, in the git folder and in each linked worktree's folder; a missing one may not be made on macOS, and on Linux, where a folder in its place would stop git, one the command makes is removed when it ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9d9f1db2af
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A runtime shutting down drops blocking work not yet started, so a placeholder a sandboxed command held, such as /tmp/.git, could be left behind when its runtime ended, and Sonny then took folders under /tmp for a repository's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
A linked worktree's folder could be swapped for a link to another repository's before the removal followed it. One without commondir was made since, and serves only a checkout the bot made. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: fd8bd93815
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fd8bd93815
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Main now picks a lead's tools by its model (apply_patch or edit, web search), so a project's lead takes its gate for the tools the client gives it, and the client leaves out of a gate any tool the lead doesn't have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013jkdGHSSeQctmSznfdNuRg
|
On 1c74670 the This looks like a flake unrelated to this PR's changes:
This session can't re-run jobs (403). Merging now, per George's call to merge everything for the release. Generated by Claude Code |
With #265 and #276 merged, sandboxing becomes Sonny's default, as Codex's modes do it and as decided for this project: leads and tasks run
workspace-writewith the network on, and their repository's git folder is writable so commits don't ask.What changes
Sonny
/approvalsmode sets the lead's sandbox along with its gate.auto(a new lead's mode) andask, the lead runsworkspace-writewith the network on. Its repository's git folder (git rev-parse --git-common-dir) is passed aswritable.full, the lead runsdanger-full-access, as Codex's full access does.configure.start_taskalways starts the task with--sandbox workspace-write --network, plus the task folder's repository as--writable, whatever the lead's mode.Daemon
configuretakessandbox,writableandnetwork. These are the namescreate's settings use, and the request replaces the bot's sandbox.Settings::underused when it was made.configureat all, as before.writableroot keeps what git runs read-only, as.gitis kept:hooks,configandconfig.worktree. A repository's missinghooksfolder may not be created. Without this, a bot that may commit could write a hook that git later runs outside any sandbox.Notes
fulllead: they are sandboxed and take the lead's empty gate, so any call that leaves their sandbox is refused rather than asked. This matches the design ("tasks always workspace-write").sandbox_unavailable, which is the daemon's existing rule that a sandbox is never silently skipped.HEADfile, one stat. Nothing changes on the request path.Tests
test_approvals), on a repository with a linked worktree:configuresandboxes an unsandboxed bot.danger-full-accessstaysworkspace-write.networkwithoutsandboxis refused.git commitin the worktree works..git/hooks/pre-commitand appending to.git/configboth fail.test_served): a task started bystart_taskhasworkspace-write, the network on, and the repository's.gitaswritable.configand new hooks.fullfor leads and outside a repository.cargo test --workspacewithAGENT_TEST_SANDBOX=1passes.test_approvals,test_served,test_answered,test_lookoutandtest_triggermodules pass.macOS isn't run here. The Seatbelt profile uses the same roots and read-only lists, so it gets the git rules without its own change.
Generated by Claude Code