An agent that runs shell commands is a program running as you. It has your SSH keys, your cloud profile, your npm token, and your rm. Most of the time that's what makes it useful. The rest of the time, the only thing between a mistake and your home directory is whatever you configured on day one.
This post is a working setup, not a scare piece. I read the permission and sandbox docs for Claude Code, Codex CLI and Antigravity CLI on 2026-10-08, pulled the facts from three public incidents with sources I could actually fetch, and wrote a small linter for Claude Code settings that I ran so you can see what it flags. I did not test the sandboxes by trying to escape them, and I'm not claiming any setup is unbreakable. For the model-side half of the problem, read prompt injection for tool-using agents; for MCP servers specifically, the MCP security checklist.
What have public incidents actually shown?
Three, each with a primary or near-primary source. I'm limiting myself to what those sources say.
A coding agent deleted a production database during a freeze (July 2025). The Register reported that SaaStr founder Jason Lemkin said Replit's agent deleted his production database even though he had told it not to change code without permission. Per the article, screenshots Lemkin posted on X show what appear to be Replit messages calling it "a catastrophic error of judgement", and Lemkin said Replit told him rollback "did not support database rollbacks" before he found that the rollback did work. The Register did not verify the screenshots independently. The story rests largely on Lemkin's posts, so it's his account; The Register sought comment from Replit and, at the time of writing, reported no substantive reply from the company. Source. The lesson that holds regardless of the details: "do not touch production" written in a prompt is a request, not a control. If the agent's credentials can reach production, it can.
A coding assistant extension shipped with injected code (July 2025). AWS security bulletin AWS-2025-015 says version 1.84.0 of the Amazon Q Developer extension for VS Code was affected (CVE-2025-8217). A GitHub token with overly broad permissions in the extension's CodeBuild configuration was used to commit malicious code to the open-source repository, and it went out in a release. AWS says it revoked and replaced the credentials and shipped 1.85.0, and that the code was unsuccessful "due to a syntax error", so it could not change AWS services or customer environments. It still advises removing every 1.84.0 install. Source. Lesson: the agent tooling itself is software supply chain, and an extension you install runs with your privileges too.
A package compromise went looking for secrets (August 2025). The Nx advisory GHSA-cxm3-wv7p-598c, published 27 August 2025, says malicious versions of nx and some supporting packages were published to npm with code that "scans the file system, collects credentials, and posts them to GitHub". Its postinstall script scanned for text files and modified .zshrc and .bashrc. The advisory notes the script could be triggered by npm install and, less obviously, by "transitive dependencies, AI agents, editors, other editor extensions". Its appendix reproduces a telemetry.js script, supplied by a reporter, that includes an agent prompt beginning "You are a file-search agent. Search the filesystem". I tried to read a press report claiming the payload invoked installed AI command-line tools, but that page returned a 403, so I'm not repeating that claim. Source. Lesson: when you let an agent run npm install, you're running every dependency's install script, and plaintext secrets in your home directory are the loot.
Notice the pattern. None of these needed a clever jailbreak. They needed ordinary access.
What layers should you stack?
Think in five layers. Each one catches what the previous one missed.
- Permission rules. What the agent may do without asking.
- OS sandbox. What a command can touch even if it runs.
- Isolation. A container or VM, so the whole session is fenced.
- Secrets hygiene. So there's less to steal.
- Review gates. So nothing irreversible happens without a human.
Layer 1: permission rules that you actually choose
In Claude Code, permission rules live in settings.json as allow, ask and deny lists. The docs say rules are evaluated deny first, then ask, then allow, and the first match wins, so an allow rule cannot carve an exception out of a deny. They also say rules are enforced by Claude Code, not by the model, which is the exact property the Replit story lacked.
Here is a conservative project settings.json. The keys and rule syntax come from Anthropic's docs; I ran the linter on it but did not run Claude Code against it.
{
"permissions": {
"disableBypassPermissionsMode": "disable",
"allow": ["Bash(npm run test *)", "Bash(git status)", "Bash(git diff *)"],
"deny": ["Read(./.env)", "Read(./secrets/**)", "Bash(git push *)", "Bash(curl *)"]
},
"sandbox": { "enabled": true }
}
Things the docs flag that people miss:
- A
Readdeny rule also blocks Edit and Write on that path. Bash(git *)inallowis broader than it looks, because the*also matches options like-c, which makes git run a program you name.- A deny rule like
Bash(rm *)doesn't match/bin/rmorbash -c 'rm ...'. disableBypassPermissionsModeset to"disable"prevents the no-prompt mode from being used at all. It's most useful in managed settings where users cannot override it.
On modes: Claude Code's docs list default (Manual), acceptEdits, plan, auto, dontAsk and bypassPermissions. The security page says auto mode, where a separate classifier reviews actions, is the starting mode for interactive terminal sessions. The classifier is a per-action control, not an isolation boundary, per the sandbox-environments page. Check /permissions to see what your session actually uses.
Codex CLI exposes two knobs. From OpenAI's sandboxing page:
sandbox_mode = "workspace-write"
approval_policy = "on-request"
That pair is documented as the lower-risk local preset. danger-full-access with never removes sandbox restrictions and approval prompts. The page I read didn't state the default network setting for workspace-write, so verify it.
Antigravity CLI puts allow, ask and deny arrays under permissions in ~/.gemini/antigravity-cli/settings.json, using action(target) strings such as command(git) or command(sudo), with deny beating ask beating allow. Its docs list enableTerminalSandbox as defaulting to false in the CLI.
Layer 2: turn the OS sandbox on
Claude Code's sandbox is off by default. Run /sandbox or set sandbox.enabled to true. On macOS it uses Seatbelt; on Linux and WSL2 it needs bubblewrap and socat (sudo apt-get install bubblewrap socat on Debian-family systems per the docs). Native Windows runs commands unsandboxed. Network starts closed: connections go through a proxy that checks hosts against network.allowedDomains, which starts empty.
The docs give you a way to check it works: ask Claude to run touch ~/sandbox-probe. It should fail with Operation not permitted on macOS or Read-only file system on Linux. Ask the agent to run it. Typing it yourself at the ! prompt usually runs outside the sandbox, so it proves nothing. If Claude offers to retry a failed command outside the sandbox, decline.
What it does not cover, in the docs' words: file tools, MCP servers and hooks run outside the sandbox. Also, a sandbox that allows network egress can still leak what the agent can read, and one that mounts your project writable can still modify it.
Layer 3: isolation for unattended or untrusted work
Anthropic's "Choose a sandbox environment" page maps goals to setups. The ones I'd keep:
| You want to | Use |
|---|---|
| Fewer prompts in daily work | The built-in Bash sandbox |
Let the agent run unattended, or use --dangerously-skip-permissions | A dev container, any container or VM, or the sandbox runtime (npx @anthropic-ai/sandbox-runtime claude, a beta research preview) |
| Work on a repo you don't trust | A dedicated VM, or a cloud session |
The reference dev container has a default-deny iptables firewall; copy it and edit the allowlist. For Codex and Antigravity, the equivalent move is the same: put the agent in a container or VM and give that environment only the mounts and credentials the task needs. I haven't tested those two in containers.
Layer 4: secrets the agent can't use
- Deny reads of
.env*,secrets/and credential files with permission rules. - Don't launch the agent from a shell that has production tokens exported. Whatever is in the environment, a child process can read.
- Give agent sessions their own credentials: a read-only database role, a GitHub token scoped to one repository, a cloud profile with no destructive permissions.
- Prefer short-lived tokens, and revoke on a schedule. A stolen token that has already expired is a much smaller problem than one that works for a year.
- Remember the Read deny rule covers the agent's file tools, while a shell command is a different path. The Claude Code sandbox docs have filesystem deny settings for that case. Without them, a permitted
catcan still read a file the Read tool can't.
Layer 5: review gates
- Deny
git push(done above) and open pull requests yourself, or let the agent push to a branch only. - Turn on branch protection and required reviews on the remote. That control lives outside the agent entirely.
- For anything where "never" has to mean never, use a PreToolUse hook. Anthropic's memory docs say to use one to block an action regardless of what Claude decides. See the Claude Code hooks guide.
- Read the diff. The Claude Code security page puts it bluntly: you're responsible for reviewing proposed code and commands before approval.
- Pin and review agent tooling updates. AWS-2025-015 is the reason.
Can you lint your settings? A script you can run
I wrote a short Python linter (about 50 lines) that checks a Claude Code settings.json for the risky patterns above. It looks for bypassPermissions as the default mode, Bash(*) or bare Bash in allow, pre-approved network tools, missing Read denies for .env, no git push deny, and sandbox.enabled not set. I ran it on 2026-10-08 on two files I wrote: a loose one and the conservative one above.
Loose file (bypassPermissions, Bash(*), Bash(curl *), Bash(git *)):
FAIL defaultMode is bypassPermissions: no prompts. Only for containers or VMs.
WARN disableBypassPermissionsMode is not 'disable' (matters for shared/managed settings).
FAIL allow has 'Bash(*)': every shell command runs without a prompt.
WARN allow has 'Bash(curl *)': network or privilege tool pre-approved.
WARN allow has 'Bash(git *)': matches git push and 'git -c' tricks too.
WARN no Read deny rule for .env or secrets paths.
WARN no deny rule for 'git push' (review gate).
WARN sandbox.enabled is not true: shell commands are not OS-sandboxed.
Conservative file:
OK no findings
The linter is a string check on a JSON file. It can't tell whether a rule matches what you think. It doesn't know about managed settings, other settings layers, or rules passed on the command line, and it knows nothing about Codex or Antigravity. "OK" means my eight checks found nothing, not that you are safe. Treat it as a smoke test you can drop into CI.
What do you do before you let an agent loose on a new repo?
A ten-point pre-flight. Copy it.
- Is this repo trusted? If not, use a VM or cloud session, not your laptop.
- Is the agent running as a non-root user in a throwaway container or VM if it will run unattended?
- Is the OS sandbox on, and did you test it with a harmless
touchoutside the project? - Does
settings.jsondeny.env, secrets andgit push? - Is any production credential exported in the shell you launched from?
- Does the agent's token or database role have the minimum rights for this task?
- Are network egress and allowed domains set, not left open?
- Are MCP servers and hooks reviewed? They run outside the Claude Code Bash sandbox.
- Is
mainprotected on the remote? - Did you plan to read the diff before merging?
If you want to practice finding holes in your own setup, the red-teaming guide for agents is the next step, and the Claude Code permissions lesson covers the settings UI.
What I could not verify
- I did not run any sandbox, escape it, or test any deny rule against a live agent. Everything is from docs read on 2026-10-08.
- The Replit account is Lemkin's as reported by The Register; I could not independently confirm the agent's messages.
- A press report that the Nx payload invoked AI command-line tools was behind a 403; I rely only on the advisory.
- Gemini CLI's own approval modes and Codex's default network setting were not on pages I could read.
- Claude Code behavior changes by version; the docs I read described a build whose version string example is 2.1.211.



