Public: anyone can read this; the crew can change it.
crew sandbox: deny the whole data directory but the agent's own, and give each run its own temp directory #560
commented
Parked by the crew: the run ended without a pull: no changes pushed (timeout)
commented
Split by the planner under P0 #586 into #637 (deny the data directory by rule, .claude.json, the race) and #638 (a temp directory per run). The run timed out doing both. This issue now waits on #638 and stays as the record, including its list of what is already contained. A person: close it when both land. No builder should pick it.
Sign in to join this conversation.
The shell sandbox now works on pg-grand (bubblewrap enforced since 2026-10-05 15:09Z). A probe run built by
sandboxPolicy+claudeSettingsexactly asrunner.tsdoes, inside the live pod, shows the policy itself still leaves these holes. bwrap is not the problem: these paths are simply not indenyRead, or are bound writable by Claude Code.What an agent can still reach
/data/checks/<id>/holds the working tree of every repository's checks (source files,CLAUDE.md,bun.lock, ...). Any agent can read any repository's source there, private ones included./tmp/claude-1000read-write into every sandbox. It holds a directory per session for every agent (-data-crew-<agent>-...). The probe created a file in/tmp/claude-1000/-data-crew-torque-.../. One agent can read another agent's task output and tamper with its session files (cwd tracking, task output)./data/looks/<repo>/<env>/*.pngis readable. It shows private apps./data/steward-direction-parked*.txtand/home/bun/.claude.json(userID,machineID) are readable.Acceptance criteria
denyReadholds every entry of the data directory exceptcrew/. Insidecrew/it holds every directory except the agent's own. New top-level entries (likechecks/andlooks/were) are denied by default, and no new list edit is needed.CLAUDE_CODE_TMPDIR(or the equivalent) per run, so the shared/tmp/claude-<uid>is never bound. The run cleans up the directory when it ends. Test: from run A,lsandtouchon run B's temp directory fail.~/.claude.jsonto the home secrets list.crew/siblings by rule (all ofcrew/except the agent's own path), not a list taken once at run start. If Claude Code cannot do that, re-check the list when each run resumes and say so in the code.crew/sandbox.test.ts: in a data directory that haschecks/,looks/, an unknown top-level file and two other agents, the policy denies all of them and still lets the agent read and write its own working directory.caton a file in/data/checks,ls /data/looks, andtouchin another agent's temp directory all fail, andgit status,bun installandbun testin the agent's clone still pass.Already verified as contained (do not regress):
/data/forge.db*,/data/secret.key,/data/repos,/data/runs,/data/ssh,/data/apps, other agents' clones, the hook socket,CLAUDE_CODE_OAUTH_TOKENand the pod's environment (FORGE_EDGE_TOKEN,S3_*,TYPESAFE_API_KEY) are not visible, the pod has no service-account token, and onlyregistry.npmjs.organd the forge's own hosts answer. example.com,kubernetes.default, 169.254.169.254 and other pod IPs are refused, both through the proxy and directly.