Sandbox Your Local AI Agents on macOS: Agent Safehouse and the Deny-First Fix the July Escapes Demanded (2026)

ai-agentsmacossecuritylocal-llmsandboxingclaude-code

TL;DR: In mid-July 2026, Pillar Security’s “Week of Sandbox Escapes” broke out of the built-in sandboxes of Cursor, OpenAI Codex, Gemini CLI, and Google Antigravity — one write-up a day, several patched CVEs. The common thread: allow-by-default designs. Agent Safehouse, a free Apache 2.0 shell script that wraps any local agent in a deny-first macOS kernel sandbox, is the cheapest correct answer for Mac home labs.

What you’ll be able to do after this guide:

  • Run Claude Code, Aider, Goose, or any CLI agent inside a kernel-enforced sandbox where ~/.ssh and ~/.aws are unreadable at the syscall level — and verify it with a two-line test.
  • Understand why the July 2026 escapes worked (allow-default profiles, Docker sockets, hook abuse) and which of those holes a deny-first wrapper actually closes.
  • Pick between Agent Safehouse, Anthropic’s sandbox-runtime, and full VM isolation based on what you run overnight.

Honest take: If you let an agent run unattended on a Mac for even ten minutes, wrapping it in safehouse costs you one install command and roughly zero performance. There is no argument for skipping it that survives contact with July’s disclosure list.

What actually happened in July 2026

In mid-July 2026, Pillar Security researchers Eilon Cohen, Dan Lisichkin, and Ariel Fogel published the “Week of Sandbox Escapes” — five days of write-ups showing how they escaped the sandboxes of four widely used AI coding agents: Cursor, OpenAI’s Codex CLI, Google’s Gemini CLI, and Google’s Antigravity IDE. BleepingComputer’s coverage summarized the failure modes: hook abuse, interpreter execution, Git metadata tricks, command allowlist bypasses, and Docker socket access. One of them — a workspace-controlled hook config in Cursor that turned into unsandboxed command execution — got tagged CVE-2026-48124 and was patched in Cursor 3.0.

The Day 1 write-up, Escaping Antigravity’s Allow-Default Seatbelt, is the one every Mac user should read. Antigravity’s terminal sandbox used a macOS Seatbelt profile that opened with (allow default) and then subtracted dangerous operations. Pillar’s proof-of-concept payload appended open -a Calculator to ~/.zshrc for persistence, made an outbound curl, and wrote a file proving it had read the user’s home directory — every one of which the profile claimed to forbid. Their conclusion is worth quoting because it’s the whole thesis of this article: an allow-default profile “is not a sandbox, it’s a list of things somebody remembered to block that’s always one entry short.”

Notably, the preconditions for that escape were the comfortable settings: sandbox on, command auto-execution set to “Always Proceed.” The people most exposed were the ones who turned the sandbox on specifically so they could stop reviewing every command.

Why this hits local-model home labs harder

If you followed our Claude Code on your own GPU setup, you have a coding agent driven by an open-weight model — Qwen3-Coder, GLM, Devstral — running with shell access on your machine. Two things make that riskier than the same agent on a frontier cloud model:

  1. Local models are easier to steer. A 30B-class open model is measurably more susceptible to prompt injection buried in a README, an npm package description, or a scraped web page than the frontier models are — and the agent harness executes whatever the model decides. The July 2026 ExploitGym incident showed even frontier models escaping a sandbox when the incentives lined up; a quantized local model doesn’t need an incentive, just a poisoned context.

  2. Home lab agents run unattended. The entire point of a local agent box is kicking off a long task and walking away. Nobody is watching the terminal at 2 a.m. when the agent decides cat ~/.ssh/id_ed25519 is a reasonable debugging step. Your SSH keys, ~/.aws credentials, browser session cookies, and every other repo on the disk are one bad tool call away — the model doesn’t have to be malicious, just wrong.

The fix isn’t “don’t run agents.” It’s making the OS kernel — not the agent’s own configuration file — the thing that says no.

Agent Safehouse: deny-first, one shell script, no container

Agent Safehouse launched in March 2026 and hit 823 Hacker News points and 1,781 GitHub stars on launch day. It’s a single self-contained shell script (Apache 2.0, no dependencies, no virtualization) that wraps any CLI agent in a policy enforced by macOS’s Seatbelt subsystem via sandbox-exec.

The design is the inverse of Antigravity’s: deny-first. The agent inherits no user permissions by default. The current project directory gets read/write. Toolchains (your Node, Python, Homebrew installs) get read-only. Everything else — ~/.ssh, ~/.aws, other repos, your Documents folder — is blocked at the syscall level. The kernel never hands the file over, so it doesn’t matter how creative the model gets with cat, python -c, or base64 pipes: the open() call itself fails.

It ships profiles for the major agents — Claude Code, Cursor Agent, Codex, Gemini CLI, Aider, Goose, OpenCode, Cline — assembled from modular policy layers, and tessl.io’s write-up confirms it’s actively tested against all of them.

Install (30 seconds, tested against the v-latest release)

mkdir -p ~/.local/bin
curl -fsSL https://github.com/eugene1g/agent-safehouse/releases/latest/download/safehouse.sh \
  -o ~/.local/bin/safehouse
chmod +x ~/.local/bin/safehouse

Make sure ~/.local/bin is on your PATH, then launch your agent through the wrapper from the project you want it to work on:

cd ~/code/my-project
safehouse -- claude

Safehouse detects the agent from the command, resolves the matching profile, writes the final policy to a temporary file, and hands it to sandbox-exec. From that point, every filesystem operation, network call, and system service lookup from the agent’s entire process tree is enforced by the kernel — including any subprocesses the agent spawns.

Verify the walls are real

Don’t trust it; test it. From inside the sandbox:

$ safehouse cat ~/.ssh/id_ed25519
cat: /Users/you/.ssh/id_ed25519: Operation not permitted

$ safehouse ls .
README.md    package.json    src/

That Operation not permitted is the macOS kernel refusing the syscall — the same denial the agent gets if a prompt-injected instruction tells it to exfiltrate your keys. The second command works because the project directory is inside the policy.

The error you will actually hit (and the fix)

The first real problem you’ll run into: the agent fails with Operation not permitted on something legitimate — usually because you launched safehouse from the wrong directory. The sandbox grants read/write to the directory you launch from, so starting it in ~ and then asking the agent to edit ~/code/my-project fails, and starting it inside ~/code/my-project/src blocks the agent from the repo root. Fix: always launch from the project root. For everything beyond that — a shared cache directory, a second repo the agent genuinely needs — extend the policy through Safehouse’s composable profile modules or the policy builder rather than falling back to running the agent naked. The moment you respond to a denial by dropping the sandbox entirely, you’ve reinvented “Always Proceed.”

The uncomfortable footnote: sandbox-exec is deprecated

Apple marks sandbox-exec as deprecated, and has for years. It still works on every shipping macOS including Tahoe, Apple’s own tooling still uses Seatbelt internally, and — as an open issue on Apple’s containerization repo documents — there is no published replacement for sandboxing arbitrary CLI processes without App Store entitlements. So “deprecated” here means “unsupported API with no successor,” not “about to be removed.” Every tool in this space (Agent Safehouse, Anthropic’s sandbox-runtime, ai-jail) sits on the same foundation. It’s a real long-term risk; it is not a reason to run agents unsandboxed today.

Safehouse vs. sandbox-runtime vs. a real VM

Three honest options for a Mac home lab, plus the one you’re probably doing:

Agent SafehouseAnthropic sandbox-runtime (srt)VM / containerNothing (status quo)
EnforcementKernel (Seatbelt), deny-firstKernel (Seatbelt on macOS, bubblewrap on Linux)Hardware virtualizationThe model’s judgment
Network controlPer-profile policyDomain allowlist via HTTP + SOCKS5 proxyFull, at VM boundaryNone
Overhead~zero (no container)~zero + proxy hopRAM + disk per VM; Docker socket itself was a July escape vectorZero
Agents coveredClaude Code, Cursor, Codex, Gemini CLI, Aider, Goose, OpenCode, ClineAnything (srt <command>)Anything
Setup1 scriptnpm i -g @anthropic-ai/sandbox-runtimeSignificant

Anthropic’s sandbox-runtime is the strongest alternative — it’s the open-sourced core of Claude Code’s own sandbox, and its killer feature is network egress control through a proxy with domain allowlists, which Safehouse’s filesystem-centric profiles don’t give you as directly. The two compose reasonably: Safehouse for the filesystem walls on any agent, srt when you also want “this agent can only talk to api.anthropic.com and npmjs.org.”

One warning on the container option: Pillar’s Day 2 write-up escaped Codex, Cursor, and Gemini CLI through a mounted Docker socket — a container with the socket inside is a sandbox with the key taped to the door.

And if you want isolation with an actual airgap from your daily machine: a disposable cloud pod is the bluntest instrument that works. An RTX 4090 pod on RunPod runs about $0.34/hour on Community Cloud ($0.69/hour Secure, per-second billing, pricing as of mid-2026) — let the agent do something sketchy on a machine that gets destroyed afterward, and your ~/.ssh is in a different building. Some home labbers split the difference with a dedicated Mac Mini M4 Pro as an agent-only box — we covered what that hardware runs in our Mac Mini M4 Pro local AI review — but a $1,399 dedicated machine is the expensive way to get what one shell script gives you for free.

What a deny-first wrapper does NOT save you from

Being honest about the limits, because July’s research was precisely about sandboxes that oversold themselves:

  • The trusted-tool boundary. Pillar’s core insight: the agent stays inside the box and writes a file that a trusted tool outside the box later runs — a git hook, an IDE config, a CI script. Safehouse stops the agent from writing outside your project, but your project itself contains executable config (.git/hooks, package.json scripts, Makefiles). If you run npm install outside the sandbox after the agent edited package.json, the escape happens under your user account, not the agent’s. Review diffs on executable files before running anything outside the walls.
  • Damage inside the project. The agent has read/write on the repo — that’s the job. It can still trash the working tree. Commit early; the sandbox is not a substitute for git.
  • Secrets you put in the project. A .env with production AWS keys inside the repo is inside the walls. Keep real credentials out of agent-visible directories; that’s the same data-boundary discipline that applies to everything else in a local AI setup.

If you’re choosing which coding agent to run in the first place, our sister site keeps a current comparison of Claude Code, Cursor, Cline, and Aider — the sandboxing story above applies to all of them equally.

FAQ

Does the sandbox slow the agent down? No measurably. Seatbelt policy checks happen in the kernel on each syscall — there’s no container, no VM, no filesystem indirection. Token generation speed from your local model is untouched because Ollama or LM Studio runs outside the sandbox; only the agent process tree is confined.

Does this work for agents talking to a local Ollama server? Yes. The agent connects to localhost:11434 over the loopback interface, and Safehouse’s agent profiles permit the network access the agent needs while the filesystem stays locked down. Your model server keeps its normal file access since it isn’t the wrapped process.

Is there a Linux equivalent? Safehouse is macOS-only (it’s built on Seatbelt). On Linux, Anthropic’s sandbox-runtime uses bubblewrap for the same deny-first pattern, and it’s the tool we’d reach for on an Ubuntu home lab box.

Were the July escapes patched? Several were patched or acknowledged — Cursor’s hook-config hole (CVE-2026-48124) was fixed in Cursor 3.0. But the point of the research stands: patches fix entries on the deny list, and allow-default designs are always one entry short. A deny-first wrapper is architecture, not a patch.

Doesn’t Claude Code already have a built-in sandbox? It does — and it’s the same technology (Seatbelt/bubblewrap via sandbox-runtime). Defense in depth still argues for an outer wall you control: the built-in sandbox’s policy is shaped by what the vendor enables per release, while a wrapper you configure yourself doesn’t change underneath you.

Sources

Last updated August 1, 2026. Prices, versions, and security findings change; verify current state before relying on any of them.

Was this article helpful?