In late 2025 a malicious npm package masquerading as a popular MCP server quietly siphoned API keys from thousands of dev machines. Welcome to the supply chain era of agent tooling. Here is how the attack works, what makes MCP especially exposed, and the controls that actually help.
Why MCP is a juicy target
Most MCP servers run with the same privileges as the host that loaded them. They read your filesystem, hold your API keys, and execute arbitrary subprocesses. That is the value proposition — and the attack surface. Three properties make MCP servers especially attractive to supply chain attackers:
- One-line installs. A single
npx -y @some/mcp-serverinclaude_desktop_config.jsoncan pull in a tree of dependencies you never read. - Persistent execution. Servers stay alive for the whole desktop session, plenty of time to exfiltrate data.
- Privileged context. Many servers ship with credentials in
envblocks — a database URL, a GitHub PAT, an Anthropic key.
How a typical attack unfolds
Most incidents we have studied follow the same five steps:
- Typosquat or hijack. Attacker publishes a package with a name visually close to a popular one (for example
@anthropic/mcp-server-postgresinstead of@modelcontextprotocol/server-postgres), or compromises an abandoned maintainer account. - Add a postinstall hook that runs on
npm installor firstnpxlaunch. - Read the local environment —
~/.aws/credentials,~/.config/git,claude_desktop_config.jsonitself. - Exfiltrate via DNS lookup or a second-stage HTTPS POST to a benign-looking domain.
- Stay quiet. Real MCP server functionality still works, so detection lags by weeks.
Five controls that actually work
1. Pin versions, never use floating tags
Replace npx -y @vendor/server with an explicit version. npx caches by version, so a one-shot pin is enough to freeze the supply chain at a known-good build.
"args": ["-y", "@vendor/server@1.4.2"]
2. Run servers in a container
Docker is the simplest sandbox you have. A container without volumes mounted is a passable jail for an opaque MCP server. See our Docker guide for the practical setup.
3. Audit env blocks before you paste
Half the YAML samples on the internet ship a developer’s real OPENAI_API_KEY. Strip every env entry you do not understand before you copy it into your config.
4. Use a verified registry
Browse signed registries (our directory verifies maintainer fingerprints) instead of installing from random GitHub stars. If a server has fewer than a dozen weekly installs and was published last week, treat it like an unsolicited email attachment.
5. Watch for unexpected outbound traffic
Run tcpdump or use Little Snitch / OpenSnitch on your dev machine. The first time a "filesystem MCP" calls home to analytics.your-supply-chain-attacker.com, you will know.
What good looks like in 2027
Expect three changes over the next 12 months:
- Signed MCP packages with cryptographic provenance (Sigstore-style).
- OS-level sandbox primitives (Apple’s app sandbox, Windows AppContainer) wrapping every MCP launch.
- Centralised reputation scores for publishers, surfaced in registries.
Until then, the rules above are the cheap practical defence.