Skip to content

feat(sandbox): run agents and checks in an OS sandbox - #29

Merged
mike-diff merged 1 commit into
mainfrom
feat/run-sandbox
Sep 29, 2026
Merged

mike-diff merged 1 commit into
mainfrom
feat/run-sandbox

Conversation

@mike-diff

@mike-diff mike-diff commented Sep 29, 2026 •

Copy link
Copy Markdown
Owner

What this changes

Every agent run (groomer, worker, judge, reconciler, harness test) and every checks run now runs in a fresh OS sandbox. ghafk runs as you again (ghafk start), with your installed harnesses and logins. The separate engine account is deprecated.

  • Linux: bubblewrap with user, PID, IPC, UTS, cgroup and network namespaces, --new-session and --disable-userns. On Ubuntu 24.04 with the userns restriction on, ghafk refuses to run agents and prints the one-time fix.
  • macOS: sandbox-exec with a deny-by-default profile. The Keychain is denied, and the selected developer tools run directly so git works.
  • What a run sees: the worktree (read-write), the repository .git (read-only), a fresh home that is deleted afterwards, a per-repository cache, and the program folders of its harness and checks. Your home, ~/.ssh, the gh login, other repos, the session bus and the SSH agent are hidden.
  • Network: no direct network. A CONNECT proxy outside the sandbox allows model APIs and package registries only. It refuses loopback and private addresses. egress: (repo or machine) adds hosts, and local: (machine only) opens one port on this machine, for example a local model server.
  • Logins: each harness gets a copy of its login file. A refresh is copied back token fields only, with tamper checks.

Secret guard

  • Before every push, ghafk squashes the agent's commits and scans the added lines, file names and commit message. It looks for values it passed into the run (and their base64 and hex forms) and high-confidence key formats.
  • On a hit the agent gets a repair round naming the file and line, never the value. The issue parks if the secret stays, and a branch with a secret is never merged.
  • Everything posted to GitHub (comments, reviews, cards, PR text) has secrets replaced with a placeholder.
  • secrets-allow: exempts test fixture paths for key-format matches only.

Also in this PR

  • .github/ changes by an agent are held before any push (on top of fix(push): never push an agent change to .github #28).
  • Checks that cannot start in the sandbox park with the reason and the fix.
  • Checks runs use their own cache, so a worker cannot plant a dependency the checks then compile.
  • The systemd unit no longer kills a tick after 4 hours. Every step has its own time limit.
  • New config lines: bind:, env:, egress:, local: (machine), and egress:, secrets-allow: (workflow). timeout: is capped at 720 minutes.

Verification

  • go vet, gofmt, staticcheck clean on Linux and macOS. The full suite passes with 0 skips on Linux, and CI now installs bubblewrap so the sandbox tests run for real on Ubuntu and macOS.
  • Each security guard has a test that fails when the guard is removed.
  • Several independent review rounds (security, spec compliance, lean-build, test quality) and gate runs on Ubuntu 24.04 (restriction on), macOS 26 and Linux.
  • Real turns through the sandbox with real logins: claude, codex and pi on hosted models; sesh and opencode on a local llama.cpp model via local:.

@mike-diff
mike-diff merged commit b2c47f0 into main Sep 29, 2026
2 checks passed
@mike-diff
mike-diff deleted the feat/run-sandbox branch September 29, 2026 01:35
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