Anthropic shipped OS-level sandboxing for Claude Code. If you run an agent
against a repo you care about, it's worth understanding precisely what moved —
because a fair amount of the commentary treats it as "agents are contained
now," and that's not what the documentation says.
I read the docs carefully, partly because I build a tool in adjacent territory
and needed to know whether I'd just been made redundant. Short answer: no. The
longer answer is more interesting, and it starts with a compliment: the docs are unusually honest about their own limits. Most of what follows isn't
The sandbox uses OS primitives — Seatbelt on macOS, bubblewrap on Linux and
WSL2. By default, sandboxed commands can write only to your working directory
and the session temp directory. No network domains are pre-allowed: the first
time a command needs a new host you're prompted, and approving it lasts the
session.
Crucially, this is enforced by the operating system on the running process,
not by the model correctly interpreting a command. The docs put it well: the
boundary holds regardless of what the model chose to run, and even if an
allowed command does more than its name suggests. That's a real improvement
over asking an agent nicely, and it's the right layer for what it solves.
The motivation named in the docs is the same one I keep seeing in the wild:
reducing the permission prompts that people stop reading. Approval fatigue is
the disease; this is a real treatment for part of it.
It's Bash-only. The sandbox constrains Bash commands and their child
processes. Claude Code's own Read, Edit and Write tools don't run through it —
they go through the permission system instead. "The sandbox is on" means shell
commands are contained, not that every file operation is.
Your working directory is inside the boundary by design. The default write
scope is the current working directory, plus session temp. That's what makes
the agent useful — it has to edit your code. It also means the sandbox is not
protecting the thing many developers assume it is. A destructive command
confined to your project is still confined to your project.
There's a sharp exception worth knowing, and it cuts in the reassuring
direction: even in auto-allow mode, rm
and rmdir
targeting /
, your home
directory, or other critical system paths still trigger a prompt or a
classifier check, and explicit deny rules are always respected. Anthropic
special-cased the catastrophic paths. Everything inside your working directory
remains permitted, deliberately.
Reads are much wider than writes. Default read access is the entire computer minus a few denied directories — and the docs say plainly that this
~/.aws/credentials
and~/.ssh/
. If you want those protected you configure sandbox.credentials
denyRead
. There is no built-in credential denyThere's an escape hatch, on by default — but it's permissioned. When a
command fails because of sandbox restrictions, Claude may retry it with
dangerouslyDisableSandbox
. Importantly, that retry goes through the normal
permission flow: a confirmation prompt in default mode, or the classifier in
auto mode. So it isn't a silent bypass — it's a sanctioned door with a
doorbell. If you want the door bricked up, allowUnsandboxedCommands: false
enables what the panel calls Strict sandbox mode.
It fails open. If the sandbox can't start — missing bubblewrap, unsupported
platform — Claude Code warns and runs commands unsandboxed, unless you set
failIfUnavailable: true
. That's a defensible default (a safety layer that
bricks your agent gets switched off, and then it protects nobody); I make the
same choice in my own tool. But fail-open has a shadow: the thing can be
inactive while everything looks fine. I learned that expensively when a hook
API rename left my own tool silently gating nothing for four minor versions,
with a fully green test suite.
And on native Windows it doesn't run at all. Windows users are pointed at
WSL2. If you run Claude Code natively on Windows — plenty do — the sandbox
isn't in your picture.
Before I make my argument, the Limitations section deserves reading in full,
because it's more candid than most vendor security pages:
github.com
can create paths for data exfiltration, with domain
fronting named explicitly.allowUnixSockets
can inadvertently grant host access: allowing
/var/run/docker.sock
effectively grants access to the host system.allowAppleEvents
on macOS removes code-execution isolation.enableWeakerNestedSandbox
considerably weakens security.That's a vendor telling you where their boundary ends. Take them at their word
rather than at the marketing.
Containment, consequence and recovery are three different questions, and tools
tend to answer exactly one:
Containment asks can this process touch things outside its box? That's
the sandbox, Docker, seccomp. A boundary in space.
Consequence asks what will this specific command destroy if it runs?
Fifty thousand rows. Three dependent tables. One commit that exists only on the
remote. A containment boundary has no opinion about this, because a permitted
command inside the boundary is just a permitted command.
Recovery asks and if it happens anyway, can I get it back? Neither
containment nor prediction gets you here. This is a backup taken before
execution, and a path back.
The failures I've been collecting all month live in the second and third
categories. An agent following NTFS junctions out of a Windows.old
cleanup
into someone's live Documents folder. Prompt-configured rules — "don't touch
.env" — ignored, because instructions are suggestions and the execution path
doesn't read your CLAUDE.md. rm -rf ~/.crit/reviews/$SID
where $SID
had
already been cleared, so it expanded to nothing and took the parent directory.
Notice what those share. None is an agent doing something obviously stupid.
Each is a correct-looking command whose real scope differs from its apparent scope. Containment doesn't address that class, because the command was
Turn the sandbox on. It's built in, OS-enforced, and it closes a real
category. On Windows that means WSL2 or nothing — worth knowing before you
assume you're covered.
Then convert three soft defaults into firm ones, each a one-line change:
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
]
}
}
}
Know it's broken rather than assume it's working; make the boundary hold rather
than negotiate; and stop sandboxed commands reading your keys, since the
default read policy allows it.
Then be clear-eyed that you've solved containment, not consequence or recovery. For those: least-privilege credentials — an agent token that
That last part is what I build (Termaxa,
open source, Rust). I'm obviously not neutral. But the argument survives
without it: vendors will keep shipping containment, because containment is what
a platform can own. Consequence and recovery sit at a different layer, and
structurally, no agent vendor is going to build that layer for their
competitors' agents. Anthropic won't gate Cursor. Cursor won't gate Claude
Code. If you run more than one, that layer has to come from somewhere else.
Claude Code's sandbox is a good, real improvement that answers one of three
questions well, and its documentation is refreshingly clear about where it
stops. It's Bash-scoped; reads are far wider than writes and include your
credentials by default; the escape hatch is on but permissioned; it fails open;
and it isn't there at all on native Windows.
Read the limitations section. Flip the flags that matter to you from soft to
firm. And keep a backup — because the thing that gets you won't look dangerous.
It'll look like a command you'd have approved.
*Verified against Claude Code's sandboxing documentation, August 2026. Incidents referenced are public posts from r/ClaudeAI, r/ClaudeCode and r/cursor over the past two weeks. The docs move quickly; where this and the documentation disagree, the documentation is right and I'm out of date. Termaxa is MIT/Apache, *
cargo install termaxa
— and if you can get an agent past it in a way I haven't documented, that's the most useful thing you could send me: