隔离沙箱中的 MCP 服务器:文件系统、密钥与网络权衡

隔离沙箱中的 MCP 服务器:文件系统、密钥与网络权衡

MCP 服务器应通过受限的文件系统挂载、最小权限的密钥、明确的网络策略、按 Agent 划分的工作空间边界以及日志记录来运行,从而确保工具访问不会悄无声息地扩大 Agent 的信任边界。当 MCP 服务器可以读取文件、生成子进程、安装包、调用内部 API 或为长时间运行的 Agent 会话保持状态时,沙箱非常有用。难点不在于决定 MCP 是否需要隔离,而在于决定每个工具的边界在哪里、哪些数据可以跨越该边界、以及哪些操作仍然需要人工审核。

MCP 为何改变 Agent 信任边界

模型上下文协议(Model Context Protocol)为 AI 应用提供了一种将模型与工具、提示词和资源连接起来的通用方式。这使集成更简洁,但也将每个 MCP 服务器变成了一个策略边界。如果某个服务器暴露了 read_filerun_commandquery_databasedeploy_preview,Agent 现在可以请求超出模型上下文窗口的操作。

MCP 规范描述了几条对沙箱设计至关重要的安全期望:用户应理解并同意公开的工具、宿主应在调用工具前征得同意、工具描述除非经过验证否则不可信、敏感数据应通过适当的访问控制加以保护。这些规则属于应用层面的控制。沙箱在其下方增加了运行时控制,限制了 MCP 服务器进程可以触及的内容——即使 Agent、工具描述或提示链发出了错误的请求。

将信任边界分为三层来考虑:

层级 控制内容 常见失败模式
宿主或 MCP 客户端 连接哪些服务器以及批准哪些工具调用 一个宽泛的工具被批准一次后,在更敏感的上下文中被重复使用
MCP 服务器 工具实现、身份验证、输入验证、资源访问 工具读取了比预期更多的文件、发送了更多数据或执行了更多命令
沙箱运行时 文件系统、进程、网络、密钥、生命周期和日志 服务器进程因过于靠近生产资源而继承了宿主访问权限

目标不是让每个 MCP 服务器都以相同的方式“不可信”。一个日历查询工具、一个本地代码执行工具和一个部署工具具有不同的风险特征。目标是让每个服务器的运行时访问范围不超过其执行任务所需的范围。

首先隔离什么

从那些可以改变外部状态、接触敏感数据或执行代码的 MCP 服务器开始。这些服务器最有可能将普通的提示错误转变为更严重的事件。

需要沙箱化的高优先级候选包括:

  • 执行 shell 命令、Python、Node.js、编译器、测试或笔记本的代码执行工具。
  • 读取或写入仓库、用户上传、挂载的数据集、凭据文件或生成工件的文件系统工具。
  • 保存 Cookie、会话状态、下载文件或截图的浏览器和电脑使用工具。
  • 可以查询客户记录、分析导出、工单或私人文档的数据连接器。
  • 可以创建分支、发布预览、轮换配置或修改基础设施的部署和 CI 工具。
  • 可以从注册表、Git 远程仓库或任意 URL 获取代码的包和依赖工具。

即使是风险较低的 MCP 服务器也可能需要一些控制。一个只读的公共文档搜索服务器可能不需要每个请求都启动一个微型虚拟机,但它仍应具有许可名单的网络路径、日志和速率限制。隔离应遵循工具的实际爆炸半径,而不是“MCP 服务器”这个标签。

MCP 服务器应在哪里运行

有三种常见的放置模式,没有一种是普遍正确的。

放置方式 何时使用 注意事项
与 Agent 工作空间位于同一沙箱 服务器与 Agent 当前的文件、shell 命令、浏览器会话或生成的工件紧密耦合 服务器和 Agent 共享状态,因此如果未限定挂载和密钥,受感染的工具可以看到相同的工作空间
每个 MCP 服务器或工具组一个单独的沙箱 工具需要与 Agent 工作空间更强的隔离、处理不同的凭据或执行更高风险的操作 跨沙箱的文件传输和延迟成为产品设计的一部分
沙箱外部,通过受限的 API 该工具是一个稳定的生产服务,具有自己的身份验证、授权、日志记录和速率限制 API 必须狭窄;不要仅仅因为它在沙箱外部就暴露一个宽泛的内部管理接口

在同一沙箱中运行服务器对于编码 Agent 来说很方便。MCP 服务器可以看到仓库、运行测试、检查工件并返回结果,而无需跨环境移动文件。这在工作空间本身已经是可丢弃的并且仅包含 Agent 应使用的文件时效果最好。

当工具需要不同的策略时,单独的沙箱更好。例如,一个包分析 MCP 服务器可能需要访问公共注册表的互联网,而主要的编码 Agent 则不应该。浏览器 MCP 服务器可能需要测试账户的 Cookie,而代码执行服务器绝不应看到这些 Cookie。

外部服务适合那些根本就不是“运行时工具”的工具。账单查询、功能标志读取或问题追踪搜索可能更适合作为具有服务器端授权的普通后端 API,而不是作为 Agent 计算环境中一个形式自由的服务器。

文件系统挂载和按 Agent 划分的工作空间

文件系统访问是 MCP 的便利性常常变成意外权限的地方。一个需要读取 ./src 的服务器不应继承开发者的主目录。一个写入生成图表的工具不应能够覆盖部署配置。

使用明确的工作空间边界:

  • 为每个 Agent 运行分配独立的工作空间目录。
  • 只挂载任务所需的仓库、上传文件夹、数据集或工件目录。
  • 对源材料优先使用只读挂载,对输出仅使用读写挂载。
  • 将生成的输出与受信任的源文件分开。
  • 避免挂载凭据文件夹,如 .ssh、云配置目录、浏览器配置文件或本地包管理器认证文件。
  • 在不同的用户、租户或作业之间重置或快照工作空间。

MCP 的 roots 可以帮助客户端告知服务器应操作的文件系统位置,但 roots 本身并不是一个完整的安全边界。将其视为客户端和服务器之间的协调机制。运行时仍然需要文件系统级别的限制,并且服务器应验证路径,以便请求无法通过符号链接、相对路径或存档提取技巧逃逸到预期工作空间之外。

一个实用的模式是按角色划分工作空间访问:

目录 访问权限 用途
/workspace/input 只读 用户上传、种子仓库、基准测试夹具或测试数据
/workspace/output 读写 生成的文件、报告、补丁、图表或截图
/workspace/tmp 读写,可丢弃 构建缓存、包安装缓存、临时文件
/workspace/secrets 尽可能避免文件挂载 如不可避免,挂载一个限定的密钥文件,具有严格的生命周期和脱敏处理

确切的路径并不重要,原则才是。

密钥和环境变量

密钥通常比文件更容易泄露,因为它们会通过环境变量、日志、堆栈跟踪、包脚本、shell 历史记录、浏览器会话和工具响应传播。当 MCP 服务器需要凭据时,给它能完成工具操作的最窄凭据。

为不同的 MCP 服务器使用不同的凭据。一个 GitHub 问题搜索服务器可能只需要只读的问题访问权限。一个 PR 编写服务器可能需要分支写入权限。部署服务器不应共享这些令牌,除非权限模型确实需要。

良好的 MCP 服务器密钥处理方式如下:

  • 在沙箱或进程启动时注入密钥,而不是通过提示词。
  • 当提供商支持时,使用短期或可撤销的令牌。
  • 按工具、租户、环境和操作限定凭据范围。
  • 从标准输出、标准错误、结构化工具响应和跟踪日志中脱敏密钥。
  • 不要向模型返回原始环境变量。
  • 不要让 Agent 决定加载哪个密钥。
  • 轮换高风险服务器使用的凭据,以及在疑似提示注入暴露后轮换。

避免一个常见的反模式:将包含所有用途的环境文件挂载到每个 Agent 会话中。这使本地开发更容易,但使生产审核更困难。如果某个工具不需要某个密钥,它就不应该能够读取它。

网络出站和传输选择

MCP 支持本地和远程传输模式。规范描述了用于本地进程通信的 stdio 和用于通过 HTTP 进行服务器到客户端通信的 Streamable HTTP。更早的基于 SSE 的设计仍然在生态系统中存在,但新的集成应先检查当前的 MCP 文档和所选 SDK,再依赖特定传输方式。

传输选择与沙箱网络策略解决不同的问题:

问题 传输方式回答 网络策略回答
MCP 客户端如何与服务器通信? stdio、基于 HTTP 的传输或其他支持的模式 不适用
服务器可以调用哪些外部主机? 仅凭传输方式不足够 许可名单、拒绝名单、代理、DNS 策略或无出站
服务器能否获取包或网页? 仅凭传输方式不足够 注册表许可名单、URL 许可名单、缓存和日志记录
其他进程能否访问服务器? 绑定和认证细节 入站防火墙和沙箱网络边界

对于本地 stdio 服务器,风险通常来自继承的宿主访问。服务器可能作为宿主应用的子进程运行,看到本地文件、环境变量和网络路由。如果该服务器执行代码或读取敏感文件,应将其移入沙箱进程,或将整个宿主-工作对运行在可丢弃的工作空间内。

对于基于 HTTP 的 MCP 服务器,风险转向认证、网络暴露和跨租户隔离。使用服务器端授权、TLS、相关来源检查以及按客户端分配的凭据。不要在宽泛的内部网络上暴露远程 MCP 服务器,除非有明确的策略规定谁可以调用哪些工具。

对于网络出站,默认拒绝比默认开放更容易推理。如果某个工具需要包安装,允许包注册表或拉取缓存。如果需要网络研究,通过一个记录请求域名并阻止内部元数据端点的代理路由。如果需要内部 API,暴露一个狭窄的 API,而不是整个私有网络。

包安装、子进程和长时间运行状态

许多有用的 MCP 工具需要子进程。编码 Agent 运行测试。数据 Agent 安装库。浏览器 Agent 启动浏览器。构建 Agent 调用编译器。子进程支持本身不是问题,不可见的子进程支持才是。

在允许包安装或 shell 执行之前,定义好:

  • 哪些命令被允许、拒绝或需要审批。
  • 包管理器是否可以访问公共互联网。
  • 依赖版本是否必须锁定或基于锁文件。
  • 构建缓存和已安装的包存放在哪里。
  • 后台进程可以运行多长时间。
  • 清理后保留哪些输出文件。
  • Agent 是否可以启动网络监听器。

长时间运行的 MCP 服务器引入第二个问题:状态漂移。一个存活数小时的服务器可能会累积文件、凭据、浏览器 Cookie、shell 历史、依赖更改和后台作业。这种状态可能对多步骤工作流有用,但它必须属于正确的 Agent、用户和任务。

使用生命周期控制:

控制项 重要性
按 Agent 划分的沙箱 ID 防止一个 Agent 的工具状态变成另一个 Agent 的上下文
空闲超时 清理废弃的工具会话
暂停和恢复策略 支持长时间作业,无需保持不必要的计算活动
快照或模板策略 从已知基线启动可重复的环境
显式拆除 作业完成后删除文件、终止进程并释放凭据

如果某个工具产生了持久的工件,只将这些工件复制出沙箱。除非产品明确需要完整的会话回放,否则不要保留整个工作空间。

日志记录、清理和人工审核

MCP 工具日志应能回答安全和调试问题,而不会变成一个新的密钥存储库。有用的日志包括工具名称、调用者身份、沙箱 ID、工作空间 ID、命令类别、读取或写入的文件、联系的外部域名、安装的包名、退出状态和工件路径。

默认情况下,不要记录原始提示词、原始客户数据、令牌、完整文件内容或完整命令输出。将敏感痕迹置于更严格的访问控制和保留策略之后。

即使在沙箱内,某些 MCP 操作也应保留人工审核:

  • 发布或部署到生产环境。
  • 发送电子邮件、聊天、工单、发票或面向客户的消息。
  • 修改访问控制、计费、用户数据或基础设施配置。
  • 泄露大型文件、私有仓库、数据库导出或类似凭据的字符串。
  • 在工作空间策略之外运行命令。
  • 调用具有写入权限的内部 API。

沙箱应减少爆炸半径。它不应成为从敏感业务操作中移除审核的理由。

Novita Agent Sandbox 如何适配

Novita Agent Sandbox 专为需要代码执行、文件、进程、类浏览器工作流以及长时间运行会话的隔离运行时的 Agent 工作负载而设计。它适用于工具服务器需要可丢弃工作空间(而不是直接访问开发者笔记本电脑、生产主机或共享 CI 机器)的 MCP 架构。

将其作为需要以下功能的服务器的运行时边界:

  • 执行生成的代码或命令。
  • 处理临时文件和生成的工件。
  • 在多步骤任务之间保持按 Agent 划分的工作空间状态。
  • 运行 Agent 稍后可以检查的后台工作。
  • 将 Agent 实验与应用程序主机分离。

保持产品边界清晰:MCP 服务器仍然是你的应用程序代码。你仍然需要设计工具权限、凭据范围、网络策略、审批流程、日志架构和清理行为。沙箱提供了强制执行这些决策的隔离环境。

关于产品特定的设置,请使用当前的 Novita 文档,而不是从较旧的教程中复制过时的片段。概念上,形态如下:

for each agent task:
  create sandbox from approved template
  mount only the task workspace
  inject only tool-specific secrets
  start the MCP server inside the sandbox or connect to a sandbox-backed tool API
  route tool calls through approval and policy checks
  collect logs and approved artifacts
  stop, reset, or pause the sandbox according to the task lifecycle

这使得文章级别的指导保持稳定,同时将确切的 SDK 调用留给最新的文档和你的平台代码。

实施检查清单

在将 MCP 服务器连接到自主或半自主 Agent 之前,使用此检查清单:

领域 需要回答的问题
工具范围 服务器公开了哪些工具,哪些工具会改变外部状态?
放置方式 服务器应运行在 Agent 沙箱中、单独的沙箱中,还是沙箱外通过狭窄的 API 运行?
文件系统 挂载了哪些目录,它们是只读还是读写,如何阻止路径逃逸?
密钥 注入了哪些凭据,如何限定其范围,它们可能出现在日志或输出的哪些位置?
网络 出站流量是默认拒绝、代理路由,还是按域名、注册表和内部 API 许可?
子进程 允许哪些命令、包管理器、后台作业和监听器?
状态 如何处理按 Agent 划分的工作空间、快照、空闲超时、暂停/恢复行为和清理?
日志 能否在不存储密钥的情况下重建工具调用、文件更改、外部域名和工件?
人工审核 哪些工具调用在执行、导出、部署或面向客户的操作之前需要审批?
测试 是否测试过提示注入、符号链接/路径遍历、大输出、清理失败和被拒绝的出站路径?

MCP 使工具集成更简单。沙箱化确保了这种集成不会成为模型权限的悄然扩展。正确的设计通常是混合的:一些服务器与 Agent 工作空间在同一沙箱,一些在单独的沙箱,一些在沙箱外通过具有严格授权的 API 运行。选择与工具的数据、密钥、子进程和网络需求相匹配的放置方式。

常见问题解答

每个 MCP 服务器都应该在沙箱中运行吗?

不。优先考虑那些执行代码、读取或写入文件、使用密钥、调用私有服务、启动浏览器、安装包或改变外部状态的服务器。风险较低的只读服务器可能仍然需要身份验证、日志记录和网络控制,但可能不需要每个请求都使用专用沙箱。

stdio 是否比 HTTP 对 MCP 服务器更安全?

并非自动。Stdio 对于本地服务器可以很简单,但服务器可能继承本地文件系统、环境和网络访问。基于 HTTP 的服务器需要更强的身份验证和暴露控制。更安全的选择取决于进程在哪里运行以及它接收哪些运行时权限。

MCP roots 可以替代文件系统沙箱吗?

不能。Roots 有助于在客户端和服务器之间传达预期的工作空间位置,但它们不是一个完整的运行时边界。使用路径验证和沙箱级别的文件系统控制来将服务器限制在预期工作空间内。

对于沙箱化的 MCP 工具,密钥应存储在哪里?

只注入工具需要的凭据,最好是短期环境变量或限定范围的运行时密钥。不要挂载宽泛的开发人员凭据文件夹,也不要通过提示词传递密钥。从日志和工具响应中脱敏它们。

MCP 工具何时需要人工批准?

对于生产部署、面向客户的消息、计费或访问控制更改、大型数据导出、基础设施写入以及工作空间正常策略之外的任何命令或网络操作,都需要批准。

推荐文章