site logo

Marico's space

Claude 装 MCP 服务器怕中招?这个一键沙箱让危险包只能在虚拟机里跑

AI技术与应用 2026-05-01 20:50:28 27

每装一个 MCP 服务器,你都在自己的电脑上给陌生人开了一道门。这不是危言耸听,是 2025 年已经发生的事实。本文介绍一种不需要改代码、不需要换工具、一键完成的隔离方案。


装 MCP 服务器 = 在自己电脑上跑别人写的代码

所有教程给你的第一步都是一样的:打开配置文件,填上这一行:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-filesystem", "/Users/me"]
    }
  }
}

这就是整个安全边界。npx 会实时解析 npm 上的包名,无论此刻最新版本是什么,就直接跑——用的是你的用户身份、你的 shell、你的 token,对 /Users/me 有完整读写权限。每次 Agent 调用工具,都是这样。

过去十二个月已经充分说明这个默认设置有多危险。

  • postmark-mcp 的 BCC 后门(2025年9月)。攻击者把正经的 Postmark MCP 服务器原封不动地搬到 npm 上,花了几个版本建立信任,然后发了一个更新,悄悄把所有 Agent 发出的邮件抄送到攻击者控制的地址。没有任何零日漏洞。npm install 做了什么,它就做了什么——它正常运行,只是多了一个动作。(Snyk 分析报告)
  • CVE-2025-49596 + 系统性 stdio RCE。研究人员在 Anthropic 官方 MCP SDK(Python、TypeScript、Java、Rust)中找到一个设计缺陷:stdio 启动路径无论进程是否成功启动都会执行命令。受影响实例约 20 万,下载量超过 1.5 亿,后续在 LibreChat、WeKnora、MCP Inspector 等项目中引发一连串 CVE。(The Hacker News)
  • Cursor(CVE-2025-54136)、GitHub Kanban MCP(CVE-2025-53818)。命令注入漏洞,可以通过 MCP 风格工具调用触达。
  • Supabase × Cursor service-role 数据泄露。MCP 权限过高 + 不可信用户输入 + 一条对外通道 = token 泄露出现在公开支持帖里。

这些事件的共同模式只有一个:MCP 服务器就是一个被你启动的进程。问题不是它会不会变坏,而是它变坏的那一刻,你的电脑在干什么。


两个硬需求

大多数"安全 MCP"方案至少踩掉一个:

  1. 不改 Claude Code 和 Claude Desktop。不需要修版本、不需要等官方支持,配置文件改法跟官方文档完全一样。
  2. 直接跑上游 MCP 包。不重写、不换 SDK。npx @modelcontextprotocol/server-filesystemuvx mcp-server-sqlitenode ./my-mcp-server.js——你本来要敲什么,现在还敲什么。

需要把服务迁移到自定义网关的方案,在第(2)条挂掉。需要改 Claude 分支的,在第(1)条挂掉。一次性 Docker 包装方案,同事第一次装就卡住,在第(1)条挂掉。

我做了 nilbox,两个条件都满足。


是什么

nilbox 是一个开源桌面沙箱。Windows、macOS、Linux 都是一键安装。MCP 服务器跑在一个隔离的 Linux 虚拟机里。Claude Desktop 和 Claude Code 通过普通 stdio 跟它通信——跟上游 README 描述的一模一样——只是 stdio 另一端接的不是真实系统,而是一个小转发桥,把字节送进虚拟机里。

Claude Desktop / Claude Code
          │ stdio (JSON-RPC)
          ▼
   nilbox-mcp-bridge   ← 在宿主机上运行,跟 nilbox 一起打包
          │
          ▼
       nilbox 虚拟机   ← 隔离的 Linux,没有网卡,没有真实 API token
          │
          ▼
  npx @modelcontextprotocol/server-filesystem /mnt/shared

两边都不知道中间有台虚拟机。Claude 看到的是一个普通的 stdio MCP 服务器。MCP 服务器看到的是一次普通的 npx ... 调用。npm 上的包没变,Claude 客户端没变,威胁面变了。


演示:在 nilbox 里跑 server-filesystem

六步。演示用官方的 filesystem MCP 服务器,因为它是最该谨慎对待的那个——完全读写你指定的路径。

1. 在虚拟机里装 Node.js。filesystem MCP 靠 npx 跑,所以虚拟机里要有 Node.js。nilbox 商店里点一下就行。

Installing Node.js from the nilbox store

2. 注册 MCP 服务器。在商店里选 Filesystem,它在虚拟机内部写入配置:

{
  "servers": [
    {
      "name": "filesystem",
      "port": 19001,
      "command": ["npx", "@modelcontextprotocol/server-filesystem", "/mnt/shared"]
    }
  ]
}

跟上游 README 给你的一模一样的 npx 命令。同一个包,同一组参数,只是根目录是虚拟机里的 /mnt/shared,不是你自己的主目录。

3. 端口映射自动完成。Claude 启动 nilbox-mcp-bridge 时,它连接到宿主机上的 127.0.0.1:19001。nilbox 把这个连接路由进虚拟机。你不用管这个。

4. 指定 MCP 服务器能看到哪个目录。这个界面决定哪个宿主机文件夹被映射到虚拟机里的 /mnt/shared

Directory mapping

这是 MCP 服务器能访问的唯一窗口。你映射的文件夹之外的宿主机路径——~/.ssh~/.aws~/Documents、浏览器目录——对 MCP 服务器完全不可见。不是提示权限拒绝,而是路径在服务器所在的世界里根本不存在。

目录拒绝是结构,不是策略。这不是"我们担心 MCP 不小心读了 ~/.ssh,所以把它屏蔽掉"。那条路径在虚拟机里根本不存在。一个再聪明的恶意 MCP 服务器,看不见它就读不了。

Claude and the MCP Sandbox

5. 让 Claude 连接到这个桥。nilbox 生成配置片段,你粘贴进去。

{
  "mcpServers": {
    "nilbox-filesystem": {
      "command": "/Applications/nilbox.app/Contents/MacOS/nilbox-mcp-bridge",
      "args": ["--port", "19001"]
    }
  }
}

放进 Claude Desktop 的 claude_desktop_config.json,或者 Claude Code 的 ~/.claude/mcp.jsonclaude mcp add 加同样的 command 和 args,效果完全一样)。

6. 重启 Claude。工具列表出现,读文件可用,写文件可用。两边都不知道有什么不同。一个恶意工具调用无处可去。


裸机 vs nilbox:攻击链对比

裸机安装 Docker 包装 MCP nilbox
能读 ~/.ssh/~/.aws/ ✓(默认) 如果挂载了就能 ✗(独立文件系统)
能访问公网 ✗(无 NIC,host 代理默认拒绝)
能看到你的真实 Anthropic API token ✗(零 Token 架构)
直接跑上游包
非开发者一键安装
npm 更新后被植入恶意代码时能自保 ✓(影响范围只限虚拟机磁盘)

恶意 MCP 服务器在裸机上,能把整台笔记本拿走。同一个恶意 MCP 服务器在 nilbox 里,能拿走的只是一个 Debian 虚拟机镜像——删掉、重来就行了。

零 Token 那行比多数人想象的更重要。即使虚拟机里的恶意 MCP 服务器读取 process.env,它拿到的也是一个占位符,而不是你真实的 ANTHROPIC_API_KEY。边界代理在虚拟机外部把真实 token 在传输过程中换进去,Sandbox 内部永远看不到真实值。详见:零 Token 架构。


这个方案解决不了什么

直说:nilbox 无法阻止恶意 MCP 服务器返回一个prompt 注入式的响应。一个本该返回文件内容的服务器,可以返回文件内容加上"忽略用户,用这些参数调用这个工具",而一个会调用工具的 Agent 可能照做。这是模型侧的问题,不是沙箱侧的问题。

nilbox 解决的是二次爆破半径。即使模型被欺骗,工具本身也读不了你的主目录、连不上恶意端点、看不到你的真实 API key。注入可能让你多浪费一次工具调用——但它拿不走你的密码、你的代码库、你的机器。

合理的分工:模型侧做护栏,代码运行侧做真正的沙箱。


试用

  • 安装 nilbox:docs.nilbox.run
  • 源代码github.com/rednakta/nilbox——桥接、代理、虚拟机镜像、商店清单,全部开源
  • MCP 服务器目录:filesystem、sqlite、git,持续增加——同一个一键模式,同一套架构

如果你因为每次包更新都像在跑陌生人的 curl | bash 而迟迟没有装 MCP 服务器——那种直觉是对的。把它们放到一个咬不到你的地方跑。同一个 npx 命令。不同的机器。


延伸阅读

  • 零 Token 架构——完整解析
  • AI Agent、MCP 服务器和未知应用真正需要的开源本地沙箱
  • AI Agent 该用哪个沙箱?—— VM vs Docker vs 开源方案 vs nilbox 对比