hiw3c 日报精选
MarkTechPost RSS 全文

Meet Anthropic’s sandbox-runtime: OS-Level Sandboxing for AI Agents, No Containers

Anthropic sandbox-runtime (srt) is the open-source, OS-level sandbox behind Claude Code. It restricts file and network access for agents, MCP servers and CLI tools with Seatbelt on macOS and bubblewra

来源:MarkTechPost · www.marktechpost.com

正文为英文,可一键机器翻译(仅首次需要等待)

In this article, we will discuss newly trending open sourced Anthropic’s sandbox-runtime (srt), the OS-level sandbox behind Claude Code’s sandboxed bash tool. The Anthropic sandbox-runtime limits which files a process can touch and which hosts it can reach. It does this without spinning up a container. It is also not tied to Claude Code. Your own agents, local MCP servers and plain command-line programs can run inside it.

TL;DR

  • Size: npm package @anthropic-ai/sandbox-runtime v0.0.81, about 11.4 MB unpacked, Apache-2.0, Node.js 22.12+.
  • Runs on: any macOS or Linux dev machine or CI box. macOS uses Seatbelt; Linux needs bubblewrap, socat and ripgrep. Windows is alpha.
  • Performance: sandboxing cut Claude Code permission prompts by 84% in Anthropic’s internal usage (self-reported).
  • Best: 84% fewer permission prompts, with file and network limits enforced on the whole process tree.
  • Worst: still a beta research preview, Windows support is alpha.

What is Anthropic sandbox-runtime?

Anthropic sandbox-runtime is an open-source tool that wraps any process in filesystem and network restrictions. You install it with npm install -g @anthropic-ai/sandbox-runtime, then prefix a command with srt. It works as a CLI and as a TypeScript library.

How does sandbox-runtime work on macOS, Linux and Windows?

srt uses each operating system’s own isolation primitives. Its restrictions cover the entire process tree, including scripts and subprocesses.

  • macOS: sandbox-exec with dynamically generated Seatbelt profiles. Only ripgrep is required.
  • Linux: bubblewrap with the network namespace removed. It also needs socat and ripgrep.
  • Windows (alpha): a dedicated srt-sandbox account, a Windows Filtering Platform egress fence and explicit file ACLs.

Traffic leaves only through HTTP and SOCKS5 proxies running on the host. On Linux, those proxies sit behind Unix sockets bind-mounted into the sandbox. On macOS, the Seatbelt profile allows only one localhost port. The proxies then apply your domain allowlist and denylist.

Why does it need both filesystem and network isolation?

Anthropic team argues that 1 boundary without the other fails. Without network isolation, a prompt-injected agent could exfiltrate SSH keys. Without filesystem isolation, it could escape the sandbox and gain network access.

srt’s defaults follow that logic. Reads are allowed everywhere unless denied. Writes are denied everywhere unless allowed. Network access is denied unless a domain is allowlisted.

How do you sandbox an MCP server or your own agent?

For an MCP server, change the command in .mcp.json from npx to srt. Pass the original command as arguments. Rules then live in ~/.srt-settings.json:

{
  "network": { "allowedDomains": ["api.github.com", "*.npmjs.org"], "deniedDomains": [] },
  "filesystem": { "denyRead": ["~/.ssh"], "allowWrite": ["."], "denyWrite": [".env"] }
}

For your own agent, the library exposes SandboxManager. Call initialize(config) to start the proxies. Then wrapWithSandbox() returns a wrapped command string you can spawn.

What does the 84% figure mean?

Anthropic reports that sandboxing reduced permission prompts by 84% in internal Claude Code usage. That is a self-reported number, not an external benchmark. The target is approval fatigue. Developers who click “approve” all day stop reading what they approve. A fixed boundary lets the agent work freely inside it and ask only at the edge.

Back</button> <button class="btn pri" id="fnext">Next step ▶</button> <button class="btn" id="fplay">Auto-play</button> </div> </div> <div class="pane" id="p-sim"> <div class="sim"> <div> <div class="card"> <h5>network.allowedDomains</h5> <label class="chk"><input type="checkbox" id="d-anth" checked> anthropic.com</label> <label class="chk"><input type="checkbox" id="d-npm"> *.npmjs.org</label> <label class="chk"><input type="checkbox" id="d-gh"> github.com</label> <h5 style="margin-top:12px">filesystem</h5> <label class="chk"><input type="checkbox" id="f-ssh" checked> denyRead: ~/.ssh</label> <label class="chk"><input type="checkbox" id="f-env" checked> denyWrite: .env</label> </div> </div> <div> <div class="cmds" id="cmds"> <button class="cmd" data-c="0">srt "cat README.md"</button> <button class="cmd" data-c="1">srt "cat ~/.ssh/id_rsa"</button> <button class="cmd" data-c="2">srt "curl anthropic.com"</button> <button class="cmd" data-c="3">srt "curl example.com"</button> <button class="cmd" data-c="4">srt "npm install"</button> <button class="cmd" data-c="5">srt "echo KEY=1 &gt;&gt; .env"</button> </div> <div class="term" id="term" style="margin-top:10px"><span class="dim">Pick a command. Toggle the config to see what changes.</span></div> <div class="why" id="why"></div> </div> </div> </div> <div class="pane" id="p-plat"> <div class="plat"> <div class="pc on" data-p="0"><h4>macOS</h4><span class="tag t-g">Supported</span><ul><li>sandbox-exec</li><li>Seatbelt profiles</li><li>Needs ripgrep</li></ul></div> <div class="pc" data-p="1"><h4>Linux</h4><span class="tag t-g">Supported</span><ul><li>bubblewrap</li><li>No network namespace</li><li>socat + ripgrep</li></ul></div> <div class="pc" data-p="2"><h4>Windows</h4><span class="tag t-o">Alpha</span><ul><li>srt-sandbox account</li><li>WFP egress fence</li><li>One-time install</li></ul></div> </div> <div class="desc pdetail" id="pdesc"></div> </div> <div class="pane" id="p-defs"> <div class="defs"> <div class="dc"><div class="kicker">Read</div><div class="big" style="color:#b5cc94">Allow</div><p>Allowed everywhere by default. Deny regions like ~/.ssh, re-allow with allowRead.</p></div> <div class="dc"><div class="kicker">Write</div><div class="big" style="color:#ef7a73">Deny</div><p>Denied everywhere by default. Open paths like "." and /tmp with allowWrite.</p></div> <div class="dc"><div class="kicker">Network</di