fix(jail): map scc, rtk and codegraph past the sandbox's private home - #31
Merged
Conversation
ai-jail replaces $HOME with a fresh tmpfs and binds only the command it was handed — "tools with needs beyond their install directory stay on the --map escape hatch" — then prunes PATH to what survived. So `scc launch --jail` ran RTK's preflight, wrote the block telling the agent to prefix every command with rtk, and started it where ~/.cargo/bin no longer exists; an npm-installed scc went the same way, while every rule scaffolded here answers questions with it. The agent discovers that one failed command at a time and falls back to reading whole files, which is the cost this methodology exists to remove. --map becomes the third flag scc asks for, read off `ai-jail --help` like the other two and never guessed at. A compiled binary is mounted read-only at the name PATH knows and brings nothing with it — which is also what makes the npm build work, since os.Executable is the real Go binary behind the node shim. A script brings its bin directory, its outermost node_modules and its shebang interpreter, because node resolves a script's real path before looking for anything beside it. The list is closed at scc, rtk and codegraph: what scc's own guidance names, nothing else, every mount reported in jail.maps and printed. The jail argv is now composed after the graph and RTK steps rather than beside the refusal, because a run that has just installed rtk has to map the binary it installed. The refusal stays where it was, before anything touches the workspace.
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.
The bug
ai-jail's private home replaces
$HOMEwith a fresh tmpfs and binds only the command it was handed — it says so plainly: tools with needs beyond their install directory stay on the--mapescape hatch — and then prunesPATHto the directories that survived.So
scc launch --jailran RTK's preflight, wrote the block telling the agent to prefix every command withrtk, and then started it somewhere~/.cargo/bindoes not exist. An npm-installedsccgoes the same way, and every rule scaffolded here answers questions withscc. The agent finds that out one failed command at a time and works around it by reading whole files, which is the cost this methodology exists to remove.A jail that starts an agent unable to run the tools the file in front of it names is a jail that starts a useless agent — the same failure as one that cannot reach its model, arriving a step later.
The fix
--mapbecomes the third flag scc asks for, read offai-jail --helplike the other two, with no substitute when a build does not advertise it.PATHknows and brings nothing with it. That isrtk;~/.cargo/bindoes not come along. It is also what makes the npm distribution work, sinceos.Executable()is the real Go binary behind the node shim and mounting it at the shim's path takes node out of the picture.node_modulesand its shebang interpreter, because node resolves a script's real path before looking for anything beside it. That iscodegraph.scc,rtk,codegraph— what scc's own guidance names and nothing else. Every mount is reported injail.mapsand printed in the command line; a tool scc never mentioned stays on--jail-arg.Everything else remains policy, and policy stays in
~/.ai-jail/./.ai-jail.Ordering
The jail argv is now composed after the graph and RTK steps rather than beside the refusal: a run that has just installed
rtkhas to map the binary it installed. The refusal itself stays where it was — before the graph is built or the entry file is touched — so a launch that cannot be jailed still leaves the workspace exactly as it found it.Verification
gofmt,go vet,go test ./...green. The mapping walk is unit-tested with the hidden root and the toolchain injected, covering both install shapes, a tool the sandbox already keeps, a build with no--map, and the shebang forms (env,env -S,env NAME=value).Not verified end to end: the development machine is Windows, which has no sandbox backend. The real check is
scc launch claude --jail --dry-rununder WSL2 — the printed line should carry--map <rtk path>before the--.