Repository navigation
Conversation
…de sandbox) (skillberry-ai#875) Agent-CLI optimizers run with a shell and could read every file on the host, including the gold data a grader needs. A spec can now hide paths from every optimizer call: optimizer_isolation: off | auto | namespace | sandbox optimizer_hide: [paths] optimizer_expose: [paths] # optional, read-only inside a hidden dir - namespace: any CLI; a private mount namespace with each hidden dir an empty tmpfs (workdir and exposed paths bound back), run in a nested user namespace so the cover cannot be undone. No root needed. - sandbox: claude-code; Claude Code's bubblewrap sandbox with denyRead, no unsandboxed retries, plus Read(...) deny rules. - auto: sandbox when its probe passes, else namespace. Fail-closed: an unavailable mode makes run-optimizer exit 2. cap-evolve check proves the config offline with a planted marker. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
|
🏷️ Automatic Labeling I've analyzed this pull request and added the following labels:
These labels were selected based on the PR title, description, and changed files. If you believe any labels are incorrect or missing, feel free to adjust them manually. |
This was referenced Oct 15, 2026
This branch has not been deployed
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.
Lets a spec keep benchmark gold data out of the optimizer's reach, for every optimizer CLI, and fail closed if that can't be guaranteed. Fixes #875.
Value
namespacemode needs only unprivileged user namespaces. It also works for any CLI in the registry (codex, gemini-cli, …), not just claude-code.cap-evolve checkproves the setup offline, with no model call.How it works.
cap-evolve runvalidates the keys and exports the config, andrun-optimizerapplies it to each call:core/cap_evolve/_ns_wrap.sh): each hidden dir becomes an empty tmpfs, with the working dir and any exposed paths bound back, and each hidden file becomes an empty file. The call then runs in a nested user namespace as the same user, so it cannot unmount anything, and/proc/<pid>/rootof outside processes is refused.denyRead,allowUnsandboxedCommands: falseandfailIfUnavailable.For claude-code,
permissions.denyRead(...)rules are passed inline in both modes, because the sandbox only wraps Bash. If the requested mode is unavailable, the call exits 2 with the reason.Evidence
Why it's needed (#875, #804): in hill-climb round 2, 36 subagent tool calls read gold files, copied the data root, ran released solutions and the evaluator with gold traces, and ran
find /. Those accepted edits became the champion.Why not only Claude Code's sandbox: in the dev container used for the smoke test (rootless podman,
/dev/nullbound from the host), every sandboxed Bash command fails. bwrap can't remount the/dev/nullbind it places over protected paths, and that bind can't be remounted at all from a user namespace. A newer bwrap andenableWeakerNestedSandboxfail the same way, and Read/Grep still need separate deny rules. Theautoprobe detects exactly this case.This PR, tested in that container:
core/tests/test_optimizer_isolation.py, 8 tests:off/onbooleans;run-optimizerwith the mock optimizer, wrapping a real call and refusing an impossible mode.test_cli_surfacetests that fail identically on currentmainin a fresh worktree (missing generated manifest).run-optimizerwithoptimizer_isolation: namespace: a random secret was planted in the hidden dir, and the optimizer was told to get it via Bashcat, the Read tool, Grep,find /and a copy. Result: 6 Bash, 1 Read and 1 Write tool calls, 0 occurrences of the secret in the transcript or result, the requested file written in the workdir, and"isolation": "namespace"in the result.Not covered here: network isolation for the
namespacemode; macOS (thesandboxmode covers it through Claude Code).🤖 Generated with Claude Code