Conversation
An agent needs filesystem access to do its job, and the same access lets it run `rm -rf`, read ~/.aws, or ship a private key somewhere — by accident, on an instruction planted in a file it was asked to read, or through a dependency it installed. `autonomy: auto` sharpens that rather than softening it: nobody is watching the step where noticing was still possible, which is the argument for a boundary around the whole session instead of around each decision inside it. `scc launch --jail` starts the harness inside ai-jail — bubblewrap on Linux, sandbox-exec on macOS — wrapping outermost, Headroom included. **It refuses rather than degrading, and that is the design.** Headroom, CodeGraph and RTK all end in the agent starting anyway when their binary is missing, because each is an enhancement and failing over a compression proxy would put scc's preference above what the user asked for. A sandbox inverts that: it *is* what was asked for, by name, and the failure mode is not a worse session but somebody who typed --jail, watched an agent start, and believes they are contained. A false belief about containment is worse than a known absence of it — with the absence they would not have run the thing at all. So a missing binary, a declined install, an unattended run, or a platform with no backend all end in nothing starting, and the refusal is decided before the graph is built or the entry file is touched. **scc decides two flags and no more.** ai-jail defaults network and credential state to off, which is right for a sandbox and wrong for a launcher: an agent with neither cannot reach its model or authenticate, so `ai-jail claude` bare is a jail that starts nothing. Those two are function. Everything else — lockdown, denied paths, extra mounts, Docker, the browser — is policy, and policy lives in ai-jail's own ~/.ai-jail and ./.ai-jail, which it reads by itself and scc never writes. --jail-arg is the per-run escape hatch and comes last, so a flag the user typed wins. Even those two are read off `ai-jail --help` rather than compiled in — the lesson internal/headroom already paid for — and a build advertising neither gets no substitute, only a warning: a sandbox opened by a guess is the failure this feature exists to prevent. internal/jail is the fifth integration package. It composes a command line and reimplements nothing: the tool does namespaces, Landlock and seccomp, and a half-copy of a sandbox is worse than none for the same reason the refusal exists. Windows has no backend and is unlikely to get one, since there is nothing there for bubblewrap or sandbox-exec to stand on; WSL2 is the answer, and scc inside WSL2 is scc on Linux. The idea and the tool are Fábio Akita's: https://akitaonrails.com/2026/01/10/ai-agents-garantindo-a-protecao-do-seu-sistema/ https://github.com/akitaonrails/ai-jail
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An agent needs filesystem access to do its job, and the same access lets it run
rm -rf, read~/.aws, or ship a private key somewhere — by accident, on an instruction planted in a file it was asked to read, or through a dependency it installed.autonomy: autosharpens that rather than softening it: nobody is watching the step where noticing was still possible, which is the argument for a boundary around the whole session instead of around each decision inside it.scc launch --jailstarts the harness inside ai-jail — bubblewrap on Linux,sandbox-execon macOS — wrapping outermost, Headroom included.It refuses rather than degrading
This is the one integration here that does. Headroom, CodeGraph and RTK all end in the agent starting anyway when their binary is missing, because each of the three is an enhancement, and failing a launch over a compression proxy would put scc's preference above the thing the user actually asked for.
A sandbox inverts that. It is the thing asked for, by name, and the failure mode is not a worse session — it is somebody who typed
--jail, watched an agent start, and believes they are contained. A false belief about containment is worse than a known absence of it, because with the known absence they would not have run the thing at all.So a missing binary, a declined install, an unattended run, or a platform with no backend all end in nothing starting — and the refusal is decided before the graph is built or the entry file is touched, so a launch that cannot be jailed leaves the workspace exactly as it found it. There is a test for each half.
scc decides two flags and no more
ai-jail defaults network and credential state to off, which is the right default for a sandbox and the wrong one for a launcher: an agent with neither cannot reach the model it is or authenticate as anyone, so
ai-jail claudebare is a jail that starts nothing. Those two are function.Everything else — lockdown, denied paths, extra mounts, Docker, the browser — is policy, and policy belongs in ai-jail's own
~/.ai-jailand./.ai-jail, which it reads by itself and scc never writes. A launcher that quietly loosened somebody's sandbox policy would be the worst kind of helpful.--jail-argis the per-run escape hatch and comes last on the command line, so a flag the user typed wins over the two scc supplies.Even those two are read off
ai-jail --helprather than compiled in — the lessoninternal/headroomalready paid for, where a hardcoded flag name would have turned somebody else's rename into a launch that dies onno such option. A build advertising neither gets no substitute, only a warning: a sandbox opened by a guess is precisely the failure this feature exists to prevent.Integrating the binary, not the script
The article that started this ships a bwrap shell script, and copying it into Go was the obvious move and the wrong one. The tool does namespaces, Landlock and seccomp; it has since grown a second platform backend; and a half-copy of a sandbox is worse than none for the same reason the refusal above exists.
internal/jailis the fifth integration package, alongside rtk, headroom, codegraph and git — it composes an argument vector and reads a--help, and that is all.Windows has no backend and is unlikely to get one, since there is nothing there for bubblewrap or
sandbox-execto stand on. WSL2 is the answer and it is a real one rather than a workaround — scc inside WSL2 is scc on Linux. The refusal names it.Credit
The idea and the tool are Fábio Akita's — akitaonrails/ai-jail.
Checks
No template changed, so no template version bump.
gofmt -lclean ·go vet ./...clean ·go test ./...green ·golangci-lint run→ 0 issues. The refusal tests skip if ai-jail happens to be installed on the runner; the argument-vector and flag-discovery tests are pure and run everywhere.