BlogMartin Grossupdated 15 min read

How Secure Is the Claude Code Sandbox on the Mac?

Auf Deutsch lesen

Glass cube containing a layered circuit board: an AI chip with a padlock above the layers “Virtual Machine” and “Secure Sandbox”, resting on sand
Contents (10 sections)

AI agents execute commands on your machine — but how well do the sandboxes of Claude Code and Cowork actually protect you? Both promise isolation, yet rely on entirely different mechanisms. I didn’t just read the documentation — I examined both systems from the inside using standard Linux tools. The result: the isolation is real, verifiable, and surprisingly well thought out.


Key takeaways

  • In February 2026, Cowork isolated in three layers: its own Linux VM, bubblewrap and a seccomp filter inside it, plus a proxy that only lets approved domains through.
  • Claude Code on the Mac is only protected after /sandbox. Then Apple’s Seatbelt restricts file access and networking, without a VM and without noticeable delay.
  • Writes are tightly limited, reads hardly at all: the Claude Code sandbox blocks writes to shell and Git configuration. Credentials such as ~/.ssh and ~/.aws, however, stay readable by default. If you don’t want that, you have to block them yourself.
  • You don’t have to take anyone’s word for it: the sandbox runtime is open source, and the VM can be inspected from the inside. The end of this article shows how.

“If Claude decides to delete all my files: no big deal — but only inside an isolated VM.”

Anyone who uses Claude Code in the terminal with default settings knows the drill: many commands require approval before Claude Code executes them. You constantly have to weigh whether a given command is safe or not.

“Allow this? Allow once? Allow always?”

You keep checking: is this harmless, or could this command cause problems? Cognitive load from reading command lines.

There are essentially two extremes: either you review every single permission request yourself, or you use the --dangerously-skip-permissions option, which allows everything. In between, there are many gradations. You can define your permissions with fine granularity, but that’s almost as much effort.

How nice would it be if you could simply allow everything while still being certain that nothing unwanted happens on your machine. Then agentic coding could proceed unhindered and you’d get results fast.

That’s exactly what an isolated system promises — one that runs shielded from your actual computer. Such an isolated system reduces the blast radius — the maximum damage a misguided command can cause — immensely. If something goes wrong, you simply restart and return to the last stable state. There are many ways to implement this.

One of them is the /sandbox command built into Claude Code. It activates a sandbox that restricts Claude Code at the OS level — file access and networking. You can let commands run automatically without confirming each one, because the sandbox limits what can happen. But how secure is it really?

And then there’s Cowork in the desktop version of the Claude app. Cowork is aimed more at knowledge workers than developers. It can access folders, create and modify files, install packages — all autonomously. At first glance, it’s not obvious how the protection works. There’s no /sandbox command you’d need to activate. The isolation happens in the background.

I was curious about both: how does the sandbox work in Claude Code? And how does Cowork protect me from unwanted changes on my machine?

I didn’t want to rely on the documentation alone — instead, I examined both systems from the inside. Here’s what I found.

Two Products, Two Audiences, Two Security Models

Before I dive into the technical details, an important distinction:

Claude Code is a terminal tool for developers. It executes commands on your machine — in the same context where you work. The sandbox must be manually activated (/sandbox), making it opt-in. That makes sense: developers need as few restrictions as possible to be productive. They want to run commands that a restrictive sandbox would block. But with great power comes great responsibility. You need to understand what you’re approving.

Cowork is part of the Claude Desktop app and is aimed at users who don’t want to deal with the command line. When someone asks Claude to create an Excel spreadsheet from five PDFs, they expect a result — not a discussion about file permissions. Cowork therefore needs to provide stronger protection, without requiring the user to configure anything.

The result: two different isolation models for two different risk profiles. Here’s the overview; the following sections go into detail:

Claude Code (terminal) Cowork (desktop app)
Audience Developers Knowledge workers without the command line
Activation opt-in via /sandbox always on, runs in the background
Isolation boundary Process (Apple Seatbelt, same kernel) Dedicated Linux VM (own kernel)
Additional layers Fixed write blocks for shell and Git configuration (.bashrc, .gitconfig, .git/hooks, .mcp.json …) bubblewrap + seccomp inside the VM
Reads Most of the machine, including ~/.ssh and ~/.aws Only the VM and the shared folder
File access Write access in the working directory Only the shared folder (VirtioFS)
Network Proxy with domain allowlist Proxy with domain allowlist, no direct DNS
Measured overhead low single-digit milliseconds not measured

Cowork: A Linux Inside Your Mac

This section reflects February 2026. A few things have shifted in Cowork since then: the agent loop now runs on the host, and only code execution stays in the VM. In July 2026, the “SharedRoot” flaw also became public, through which an agent got from the VM to the Mac user’s files. Details are in “Two Sandboxes, One Goal”.

Cowork launches a lightweight Linux VM via Apple’s Virtualization.framework. Not a container, but a real virtual machine with its own kernel.

What does the VM say about itself?

$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"

$ uname -r
6.8.0-94-generic

$ uname -m
aarch64

$ nproc
4

$ free -h
              total    used    free
Mem:          3.8Gi   564Mi   1.8Gi
Swap:            0B      0B      0B

$ df -h /
Filesystem      Size  Used Avail Use%
/dev/nvme0n1p1  9.6G  7.2G  2.4G  75%

Ubuntu 22.04 on ARM64, 4 cores, 3.8 GB RAM, a 10 GB disk. No swap. Lean enough for document processing and scripts, but not meant for machine learning training.

On the macOS host, the VM files live at ~/Library/Application Support/Claude/vm_bundles/claudevm.bundle/. The root image (rootfs.img) is 10 GB as a sparse file but only occupies about 7.5 GB on disk.

Alongside it sits a compressed backup (rootfs.img.zst, ~2 GB) and a few configuration files: efivars.fd, macAddress, machineIdentifier.


How Three Layers Work Together to Secure the Isolation

The VM alone would already be a solid boundary. But Anthropic stacks three layers on top of each other.

Layer 1: The VM

Apple’s Virtualization.framework provides hardware isolation. The guest has its own kernel. Even an rm -rf / inside the VM leaves the host untouched.

Layer 2: bubblewrap + seccomp

Inside the VM, Claude doesn’t run directly — first comes bubblewrap (short: bwrap). Bubblewrap is a sandboxing tool that uses Linux namespaces to isolate processes from each other — similar to what containers do, but more lightweight.

It restricts what a process can see and do: which files, which network interfaces, which other processes.

In the Cowork VM, bubblewrap is PID 1 — the very first process:

$ cat /proc/1/status | head -2
Name:   bwrap
State:  S (sleeping)

The bwrap command line (readable via /proc/1/cmdline) shows the key restrictions at a glance:

  • --unshare-net — separate network namespace, no direct network access
  • --unshare-pid — separate PID namespace, other processes invisible
  • --ro-bind / / — root filesystem mounted read-only
  • --die-with-parent — if the parent process dies, the sandbox dies with it
  • --tmpfs /etc/ssh/ssh_config.d — SSH configuration overlaid with an empty tmpfs

Additionally, a seccomp filter is loaded. Seccomp (Secure Computing Mode) is a Linux kernel mechanism that determines which system calls a process is allowed to make. System calls are the interface between a program and the operating system — opening files, establishing network connections, starting processes.

A seccomp filter can selectively block individual system calls, drastically limiting a process’s radius of action.

$ grep Seccomp /proc/self/status
Seccomp:         2
Seccomp_filters: 2

Seccomp: 2 means filter mode — there’s an active allowlist for permitted syscalls. The filter file is called unix-block.bpf and is loaded via a dedicated binary (apply-seccomp).

Layer 3: Network Isolation

No process in the sandbox has direct internet access. All traffic goes through a local proxy:

$ env | grep HTTP_PROXY
HTTP_PROXY=http://localhost:3128

$ env | grep ALL_PROXY
ALL_PROXY=socks5h://localhost:1080

The proxy runs via socat, which tunnels TCP connections into Unix sockets that lead out of the VM. On the host side, an allowlist decides which domains may pass through.

I tested it:

$ curl -s -o /dev/null -w "%{http_code}" https://registry.npmjs.org
200

$ curl -s -o /dev/null -w "%{http_code}" https://pypi.org
200

$ curl -sv https://evil-exfiltration-test.example.org 2>&1 | grep "HTTP/1.1"
< HTTP/1.1 403 Forbidden

$ curl -sv https://evil-exfiltration-test.example.org 2>&1 | grep "X-Proxy"
< X-Proxy-Error: blocked-by-allowlist

npm and PyPI get through. Everything else receives a 403 Forbidden with the header X-Proxy-Error: blocked-by-allowlist. Direct DNS lookups also fail:

$ nslookup google.com
socket(): Operation not permitted
;; no servers could be reached

This is consistent: even if a prompt injection attack were to trick Claude into sending data to an external server — the proxy would block it.


Which Files Does the VM See?

Files enter the VM via VirtioFS — a filesystem protocol designed specifically for communication between a VM and its host. Instead of simulating real hardware, host and guest cooperate deliberately (paravirtualization). This makes file access fast and low-overhead.

$ mount | grep virtiofs
/mnt/.virtiofs-root/shared/Work/.../Marketing on
  /sessions/elegant-adoring-brown/mnt/Marketing type fuse (rw,...)

Only the folder I selected in the Desktop app is mounted. Not my home directory, not my Desktop, not my Downloads — just the one folder I explicitly shared.

Plugins and Skills are additionally mounted via bindfs. Bindfs is a FUSE filesystem that remounts an existing folder at a different location — similar to a symlink, but with the ability to change permissions. This way, Skills can be mounted read-only even though they’re writable on the host. Uploads also land in a separate, read-only mount.

One detail reveals that the VM serves multiple conversations simultaneously: the /sessions/ directory contains different sessions side by side:

$ ls -la /sessions/
drwxr-x--- elegant-adoring-brown  elegant-adoring-brown  ...
drwxr-x--- nobody                 nogroup                awesome-epic-mccarthy
drwxr-x--- nobody                 nogroup                dazzling-vibrant-carson

Each session gets its own Linux user with its own UID. My user is called elegant-adoring-brown (uid 1005). The other sessions are listed under nobody — I can’t read their files.


How Does Claude Code Protect Without a VM?

Claude Code in the terminal uses a different approach on macOS: Apple’s Seatbelt (also known as sandbox-exec). Instead of a VM, a dynamically generated sandbox profile restricts the process at the OS level. Important: the sandbox must be manually activated with /sandbox — without this step, Claude Code runs without OS-level isolation.

The profile starts with (deny default) — everything is forbidden unless explicitly allowed. The sandbox runtime is open source and available on GitHub. I downloaded the npm package @anthropic-ai/sandbox-runtime and analyzed the macos-sandbox-utils.js:

  • 59 sysctl entries (50 names and 9 prefixes) are made readable (hardware info like CPU count, memory size)
  • 14 Mach IPC services on the whitelist (Fonts, Logging, Security Server)
  • Mandatory denies against writes: shell startup files like .bashrc and .zshrc, .gitconfig, .git/hooks, .git/config, .mcp.json as well as .claude/commands and .claude/agents stay blocked, even when the working directory has write access
  • Move blocking: file-write-unlink is blocked for protected paths, preventing circumvention of the denies via mv
  • Reads are largely open: credentials such as ~/.ssh or ~/.aws/credentials are readable by default. According to the docs, there is no built-in deny list for credentials. If you want to protect them, you add them yourself, for example via filesystem.denyRead

The network isolation works similarly to Cowork: all traffic goes through a proxy with an allowlist. The list of allowed domains starts empty. What happens to other hosts depends on the permission mode, normally a prompt. The difference: with Seatbelt, this happens at the process level (same kernel); with Cowork, at the VM level (separate kernel).

Why Two Models?

Claude Code is aimed at developers who need fast feedback in the terminal. The Seatbelt overhead is in the low single-digit millisecond range — I measured it on the host, no perceptible difference from a command without sandbox. Developers can selectively activate the sandbox when they want to give an agent more autonomy without having to approve every command.

Cowork gives Claude significantly more autonomy: it runs longer, creates files independently, installs packages. And it’s aimed at users who can’t assess (and don’t need to assess) which commands are being executed at the operating system level. The potential damage from an agent with local file access, code generation, and network egress is greater — and users are less able to evaluate it. Full VM isolation is appropriate here.


What I Take Away From This

The isolation is real. Not just on paper, but verifiable.

Three things convinced me in particular:

First, the proxy allowlist with the explicit X-Proxy-Error: blocked-by-allowlist header. This isn’t a silent error message but a deliberate architectural decision. You can immediately see why a connection fails.

Second, the layering. The VM alone would be good. With bubblewrap and seccomp, it gets better. All three together make it significantly harder to break out of the sandbox. An exploit would have to simultaneously bypass the seccomp filter, escape the bwrap namespace, and then break out of the VM — on a system with no direct network access.

Third, the transparency. The sandbox runtime is open source. I downloaded the macos-sandbox-utils.js code — the 59 sysctl entries, the 14 Mach services, and the mandatory denies for shell and Git configuration are all there in black and white. In version 0.0.81 from October 2026, these numbers are unchanged. The Seatbelt profile is dynamically generated, but the generating code is inspectable. The VM architecture can be examined from the inside. You don’t have to take anyone’s word for it — you can look for yourself.

If you want to look for yourself: the sandbox runtime is on GitHub. An npm pack and a look at macos-sandbox-utils.js is all it takes to understand the Seatbelt profile.


What You Can Do Now

If you’re using Claude Code and haven’t tried the sandbox yet: start a session and type /sandbox. That alone significantly reduces the effort of approving commands one by one. For everyday use, that’s often enough.

If you want to go deeper:

  • Inspect the sandbox runtime: npm pack @anthropic-ai/sandbox-runtime, unpack, read macos-sandbox-utils.js. There you’ll see exactly what’s allowed and what’s blocked.
  • Examine Cowork from the inside: Launch Cowork and ask it to run cat /proc/1/cmdline | tr '\0' '\n'. The bubblewrap flags reveal the isolation in detail.
  • Test the network: A curl https://evil-exfiltration-test.example.org inside the sandbox immediately shows you whether the allowlist is working.

What’s Next?

The current state is clear. But one question remains: will it stay this way? Claude Code and Cowork already share the agentic architecture — and there are concrete signals that the security models are converging as well:

  • Docker is delivering MicroVMs with Docker Sandboxes, specifically designed for AI agents.
  • Apple is bringing its own Containerization framework with macOS 26 — native container support on the Mac for the first time.
  • Anthropic documents DevContainers as the official path toward stronger isolation in Claude Code.

Three players, three approaches, one goal: agents should be able to do more without being able to cause more damage.

Update (October 2026): I now use one of these three options myself. My coding agents run in Apple containers. How that fits into a layered model is described in “Cage, Wall, Bouncer”. How the container is built and what I tested in it is covered in “The Wall from Inside”. And what became of my forecast on where Claude’s sandboxes are heading is in “Two Sandboxes, One Goal”.

Frequently Asked Questions

Is the Claude Code sandbox enabled by default? No. In Claude Code, the sandbox is opt-in. You enable it in a session with /sandbox. Without that step, Claude Code on the Mac runs without OS-level isolation, and you approve commands one by one.

Can Cowork access all my files? No. Only the folder you share in the desktop app is mounted into the VM. Your home directory, Desktop and Downloads stay out unless you explicitly select them. How vulnerable exactly that shared folder can be was shown by the “SharedRoot” flaw in July 2026.

Can an agent in the Claude Code sandbox read my SSH keys? Yes, by default it can. The sandbox mainly restricts writes. ~/.ssh, ~/.aws and other credentials stay readable until you block them yourself, for example via filesystem.denyRead. The agent can only send them to hosts the proxy lets through.

Can an agent in the sandbox send data to the internet? All traffic goes through a proxy with an allowlist. In Cowork, everything outside the list gets a 403 Forbidden, and direct DNS lookups fail. In Claude Code, the list starts empty; for other hosts the permission mode decides, usually with a prompt. That also slows down prompt injection attacks trying to exfiltrate data.

Does the sandbox replace keeping an eye on what the agent does? No. It limits the damage a wrong command can cause. What the agent changes inside the shared folder is still yours to review, for example via a Git diff.


Sources

← All articles