Skip to content
All posts

Anthropic sandbox-runtime (srt), Explained — and How to Harden It (Oct 2026)

October 23, 2026 · PlayCISO · Updated Oct 23, 2026
TL;DR

sandbox-runtime (srt) is Anthropic's lightweight, open-source tool that enforces filesystem and network restrictions on AI agents and arbitrary CLI processes using OS primitives — Seatbelt on macOS, bubblewrap on Linux — rather than a full container or VM. It is the sandbox Claude Code builds on, it is deny-by-default for writes and network but open-by-default for reads, and Anthropic is explicit that it is not a complete isolation boundary.

Your AI agent can run shell commands, install packages and reach the network on your behalf. So what stops a prompt-injected or compromised agent from reading your SSH keys and POSTing them to an attacker's server? In October 2026 Anthropic open-sourced the tool it built for exactly that question: sandbox-runtime, CLI name srt. This post explains what it is, how it works, where it is honest about its own limits, and ends with a concrete hardening checklist you can apply today.

What srt is

srt is, in its README's own words, "a lightweight sandboxing tool for enforcing filesystem and network restrictions on arbitrary processes at the OS level, without requiring a container." Anthropic describes it as "a research preview developed for Claude Code to enable safer AI agents." The Claude Code documentation confirms the relationship verbatim: "Claude Code builds the sandbox on the open source @anthropic-ai/sandbox-runtime package."

  • Package: @anthropic-ai/sandbox-runtime on npm; CLI: srt.
  • Install: npm install -g @anthropic-ai/sandbox-runtime. Linux also needs bubblewrap and socat; ripgrep is used for deny-path detection.
  • License: Apache-2.0.
  • Status: Beta Research Preview ("APIs and configuration formats may evolve"); Windows is alpha.

It is not limited to Claude Code. The README states it "can be used to sandbox the behaviour of agents, local MCP servers, bash commands and arbitrary processes." Usage is simply srt <command> — for example srt npm install or srt --debug curl https://example.com — and there is a library API (SandboxManager.initialize() then wrapWithSandbox()). Crucially, restrictions "cover any scripts, programs, or subprocesses that are spawned by the command," so child processes inherit the sandbox.

Primary sources, all worth reading: the sandbox-runtime GitHub repository, the Anthropic engineering blog on Claude Code sandboxing, and the Claude Code sandboxing docs.

How it works

srt leans on native OS primitives rather than a virtual machine. The README: it "uses native OS sandboxing primitives (sandbox-exec on macOS, bubblewrap on Linux) and proxy-based network filtering."

PlatformMechanism
macOSsandbox-exec with dynamically generated Seatbelt profiles; the profile allows communication only to a specific localhost proxy port.
Linuxbubblewrap with network-namespace isolation. The sandboxed process's network namespace is removed entirely, so all traffic must go through host-side proxies reached over Unix sockets bind-mounted into the sandbox. Unix-socket blocking uses seccomp filters (x86-64/arm64 only).
WindowsAlpha. A dedicated srt-sandbox local user account, a Windows Filtering Platform egress fence keyed on that account's SID, a write-restricted token, and ACLs on the work tree. Gappier than macOS/Linux — see Limitations.

Network: deny-by-default, enforced off-box

The README is blunt: "By default, all network access is denied. You must explicitly allow domains." Enforcement does not live inside the sandbox — it lives in two proxies running on the host: an HTTP proxy for HTTP/HTTPS and a SOCKS5 proxy for other TCP. A connection is evaluated in order: a deniedDomains match denies; else an allowedDomains match allows; else, under strictAllowlist, it is denied; else a per-command list is consulted; else an "ask" callback decides (no callback means denied). In Claude Code, that "ask" is the permission prompt.

There is also a resolved-address safety net: allowed hostnames are resolved and any address in a denied set — loopback, link-local, multicast, cloud-metadata endpoints (169.254.169.254), and the host's own interface addresses — is dropped. That is a built-in SSRF and metadata-exfiltration guard.

Filesystem: writes closed, reads open

This is the single most important thing to internalize. With no settings file, the default posture is "no network access, no writes outside the default write paths, and unrestricted reads." The precedence rules:

  • Reads are deny-then-allow — open by default. "By default, read access is allowed everywhere." allowRead takes precedence over denyRead.
  • Writes are allow-only — closed by default. denyWrite takes precedence over allowWrite.
  • Network is allow-only — closed by default.

Policy lives in a JSON settings file (~/.srt-settings.json by default, or --settings <path>) with network and filesystem sub-objects:

{
  "network": {
    "allowedDomains": ["github.com", "*.github.com", "npmjs.org", "*.npmjs.org"],
    "deniedDomains": ["malicious.com"],
    "allowUnixSockets": ["/var/run/docker.sock"],
    "allowLocalBinding": false
  },
  "filesystem": {
    "denyRead": ["~/.ssh"],
    "allowRead": [],
    "allowWrite": [".", "src/", "test/", "/tmp"],
    "denyWrite": [".env", "config/production.json"]
  }
}

One genuinely good behaviour to call out: a settings file that exists but fails validation is a hard error. srt exits rather than silently falling back to defaults — fail-closed, which is what you want.

The security-versus-usability balance

Anthropic frames sandboxing as a way to cut "approval fatigue" — the safety erosion that happens when a human clicks "approve" on every prompt without reading it. The engineering blog reports that sandboxing "safely reduces permission prompts by 84%" in internal usage. Treat that as Anthropic's reported internal figure, from the engineering blog; we have not independently verified it, and it was not found in the portion of the public docs we reviewed.

The tension runs both ways. Too strict, and real workflows break — the README documents several: Jest/Watchman permission errors (srt "jest --no-watchman"); Chromium/Electron, rootless podman and nested bubblewrap failing with EPERM unless allowNestedUserNamespaces: true (which the README warns weakens guarantees); Go tools needing enableWeakerNetworkIsolation to verify TLS against the MITM proxy; and Ubuntu 24.04+ needing an AppArmor adjustment. Too loose, and the sandbox stops meaning anything — the opt-out switches each trade away a guarantee (more below). Anthropic's core design statement captures why both dimensions are mandatory: "Without file isolation, a compromised process could exfiltrate SSH keys or other sensitive files. Without network isolation, a process could escape the sandbox and gain unrestricted network access."

The honest limitations

To Anthropic's credit, the README documents what srt does not protect against. Keep these front of mind — they are where over-trust bites.

  • Not a VM, not a complete isolation boundary. The docs say so outright. A kernel-level exploit is out of scope.
  • Reads are open by default. You must hand-write deny lists for secrets. Forgetting this is the most likely real-world misconfiguration.
  • Content-blind domain filtering. The proxy "does not otherwise inspect the traffic" — "allowing github.com lets a process push to any repository," and in some cases filtering "may be ... bypass[ed] through domain fronting."
  • Unix sockets are host-takeover holes. Allowing /var/run/docker.sock "would effectively grant access to the host system." On Linux without seccomp, Unix sockets are unrestricted (warning only).
  • Writable-$PATH is a code-execution escalation. Allowing writes to $PATH dirs, system config or shell rc files "can lead to code execution in different security contexts." And a writable <project>/node_modules/ copy of srt "can be rewritten by a sandboxed command, and the next srt there runs the result unsandboxed."
  • The weakening switches remove guarantees. enableWeakerNetworkIsolation is a "potential data exfiltration vector through the trustd service"; allowAppleEvents means "the sandbox no longer provides code-execution isolation"; allowNestedUserNamespaces means the mandatory denies "no longer hold"; enableWeakerNestedSandbox "considerably weakens security."
  • Linux proxy bypass. Routing relies on HTTP_PROXY/HTTPS_PROXY/ALL_PROXY, which "may be ignored by programs that don't respect these variables." (The mandatory network-namespace enforcement is the stronger lever here.)
  • Attribution, not a boundary, between concurrent commands. A sandboxed process presenting another live invocation's id gets that invocation's allows — "this is attribution, not a boundary between concurrent commands of one session."
  • No structured Linux audit. macOS can tap the sandbox violation log (log stream --predicate 'process == "sandbox-exec"'); on Linux bubblewrap has no built-in violation reporting and you bolt on strace (strace -f srt <cmd> 2>&1 | grep EPERM).

On denial, srt does three things: it blocks the operation at the OS level (returns EPERM), logs the violation via platform-specific mechanisms, and notifies the user (a permission prompt in Claude Code).

Hardening checklist — 13 concrete controls

Each item maps to a real srt mechanism. This is the "how to keep it secure" list.

  1. Deny-by-default everywhere you can. Writes and network are already closed — keep them minimal. Never widen to allowWrite: ["/"] or a blanket domain.
  2. Fix the read-default gap first. Reads are OPEN by default. Explicitly denyRead secret stores: ~/.ssh, ~/.aws, ~/.config, .env, .npmrc, cloud creds, SSH/GPG keys, browser profiles. This is the single most important manual step.
  3. Least-privilege filesystem. allowWrite only the project tree plus a scratch dir (/tmp). Never allow writes to $PATH dirs, system config, or shell rc files — that is a code-execution escalation path. Keep srt installed globally, not in a project-writable node_modules/.
  4. Network allowlist discipline. Allowlist exact domains (registry.npmjs.org, github.com, your API host), not broad wildcards. Remember the allow is coarse: github.com allows push to any repo. For path/method control, use a custom proxy rule set.
  5. Guard SSRF and metadata endpoints. Rely on (and verify) the resolved-address denylist that drops loopback, link-local, multicast and cloud-metadata (169.254.169.254) targets. Never allow a domain that resolves into internal ranges.
  6. Treat Unix sockets as privilege grants. Never allowUnixSockets for docker.sock (= host takeover) unless you fully accept that. On Linux, confirm seccomp is active (x86-64/arm64) so sockets are actually filtered; a seccomp-unavailable warning means they are NOT.
  7. Don't flip the weakening switches by reflex. enableWeakerNetworkIsolation, allowAppleEvents, enableWeakerNestedSandbox, allowAllUnixSockets and allowNestedUserNamespaces each remove a guarantee. Use only with a documented reason and compensating isolation.
  8. Fail closed, validate config. Lean on srt exiting on an invalid settings file; keep the policy in version control and lint it in CI. No silent default fallback.
  9. Audit the denials. Pipe strace / log-stream violations somewhere durable (SigNoz, syslog) so a wall of EPERMs is visible, not just a transient prompt. Review what the agent tried to reach.
  10. Defence in depth — don't treat it as a VM. For untrusted code or high-value hosts, nest srt inside a container or microVM. OS-primitive confinement does not survive a kernel exploit.
  11. Scope check for Claude Code specifically. The built-in Bash sandbox covers shell commands only; file tools, hooks and local MCP servers run with full access. For one boundary, run the whole Claude Code process under srt (or in a container/VM).
  12. Pin and review the policy per project. Different repos need different allowlists; a single global ~/.srt-settings.json drifts wide. Prefer --settings per project.
  13. Mind Linux proxy bypass. Env-var proxying can be ignored by non-conforming programs. Prefer the mandatory network-namespace enforcement and watch for tools that open raw sockets.

Bottom line

srt is a welcome, well-documented default: a low-overhead way to put filesystem and network boundaries around an agent without standing up a container for every command, and the only lightweight local tool of its kind that ships a deny-by-default domain allowlist out of the box. But its own docs are clear that it is confinement, not containment. Treat it as the inner layer — fix the reads-open default, keep allowlists tight, audit denials, and nest it inside stronger isolation when the code is genuinely untrusted. For how srt stacks up against bubblewrap, Firejail, Docker, gVisor, Firecracker and the cloud sandbox services, see our agent sandbox comparison.

Scan your MCP servers before you sandbox them
srt confines what a process can touch, but it will not tell you whether the MCP server you point it at is risky in the first place. MCP Scan inventories and checks your Model Context Protocol servers.
Open MCP Scan
Related articles
Agent Sandbox Comparison 2026: srt vs bubblewrap, Docker, gVisor, Firecracker, E2B and More
A category-honest comparison and ranking of AI-agent command sandboxes in 2026 — Anthropic's srt against bubblewrap, Firejail, nsjail, Landlock, Seatbelt, Deno/Bun, Docker, gVisor, Firecracker, E2B, Daytona and others.
One Window, Every Machine: the Security Risks of Multi-Computer AI-Agent Consoles
A new class of free, open-source tool — Muxin is the latest — runs AI coding agents (Claude Code, Codex, OpenCode, Gemini CLI, or a plain shell) across your Macs, Linux servers, Windows PCs and cloud machines from a single window, with persistent TMUX-style sessions and one-click commit/push/PR. It is genuinely useful. It also concentrates reach into every machine you own behind one app, hands autonomous agents write access and a shell on all of them, and lets those agents keep running after you close the lid — the "lethal trifecta" at fleet scale. Here is the real risk surface and how to run one safely.
Google's Project CC Gives a Family AI Agent Its Own Inbox — and Every CISO a Preview
Google Labs' Project CC is a family AI assistant with its own verified Google account, email address, and permission to act in Gmail, Calendar, Drive and Maps. Strip away the household framing and it is the clearest consumer preview yet of the hardest problem in enterprise AI: giving an autonomous agent a scoped identity, delegated data access, an action-approval gate, and an isolated runtime — plus the prompt-injection exposure that comes free with an agent that reads forwarded email.

Ready to practise the decisions these articles describe?

Run a free War Room →
🎉 New here? Use code WELCOME10 for 10% off any plan at checkout
Anthropic sandbox-runtime (srt), Explained — and How to Harden It (Oct 2026) | PlayCISO Blog · PlayCISO