feat(run): universal --enforce — OneCLI-owned OS sandbox wraps any agent - #105
Merged
Conversation
johnnyfish
force-pushed
the
feat/enforce-universal-wrap
branch
2 times, most recently
from
July 30, 2026 21:39
78215a0 to
0469372
Compare
The native enforce path borrows Claude Code's sandbox and can never generalize. This adds the wrap path: onecli generates its own Seatbelt profile (deny network-outbound except loopback) and execs sandbox-exec around the ENTIRE agent process tree, so any agent — Codex, Cursor, Gemini, a bare shell — gets OS-enforced gateway egress, including its own model API calls and every subprocess. - run_enforce_wrap.go: profile generation, availability checks, proxy env rewrite to the loopback forwarder, sandbox-exec argv assembly, and a per-agent quirks table (Codex's internal Seatbelt gets EPERM inside ours; disabled via -c sandbox_mode=danger-full-access with a user-facing notice). - run.go: --enforce now routes per agent — Claude Code keeps the native --settings integration, Docker-sandbox agents (Hermes) fail closed with an explanation, everything else gets the wrap. Proxy env is repointed before child env/config injection derives from it. - Profile decisions validated empirically: unix sockets stay allowed (local IPC: DNS, ssh-agent) except docker.sock (out-of-sandbox egress bypass); all loopback allowed (dev servers; can't leave the machine); lsopen + appleevent-send denied (out-of-sandbox URL-fetch escapes). - Live darwin test proves the OS blocks direct egress (instantly, not by timeout), allows loopback, and confines grandchildren.
johnnyfish
force-pushed
the
feat/enforce-universal-wrap
branch
from
July 30, 2026 23:20
a6593b4 to
f095bce
Compare
golangci-lint (CI lint job) flagged appendAssign: 'probes := append(direct, ...)' reused direct's backing array. Build the probe list into a fresh, capacity-hinted slice so the base 'direct' matrix is never aliased or mutated.
TestEnforceWrapArgv asserted the macOS sandbox-exec argv shape, but the test isn't build-tagged, so it ran on the Linux CI build job where the sandbox fallback returns a bare argv — failing the build. The OS-launcher shape is the sandbox package's concern (covered by its darwin tests); the cmd-level contract is only that agent args are present and per-agent quirk flags are appended last. Assert that instead, so the test holds on every platform.
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.
What
onecli run --enforcenow works for any agent, not just Claude Code.The native path borrowed Claude Code's own sandbox, which can never generalize (most agents have no sandbox to borrow). This PR inverts ownership: onecli generates its own Seatbelt profile (deny
network-outboundexcept loopback) and execssandbox-execaround the entire agent process tree. Every child — bash commands, curl, python, MCP servers, and the agent's own model API calls — inherits the sandbox and has exactly one network path: the loopback auth forwarder fronting the gateway. Direct dials fail at the OS even with proxy env stripped.Same primitive Anthropic's sandbox-runtime standardizes; ours is the network-governance subset, chained to the gateway where policy/vault/audit live.
Routing
--settingsProfile decisions (validated empirically)
lsopen+appleevent-senddenied:open/LaunchServices launch apps outside the sandbox (URL-fetch escape).-c sandbox_mode=danger-full-access, with a user-facing notice (network governance moves to our sandbox, strictly stronger; FS safety falls back to Codex approvals).Validation
curl https://example.comvia gateway → 200. Codex wrapped: full session through gateway, shell commands working, bypass attempts (env -u, --noproxy) denied.onecli run --enforce -- claude -p ...still works.Not in this PR (phase 1b+)
Linux netns backend, Claude-under-wrap convergence, enroll shims.