展开文章目录
MCP 把工具、资源和提示模板抽象成模型客户端可协商的接口。它降低了集成成本,也让“模型可以调用什么”变得更明确。但能力列表不是安全策略;真正的风险发生在宿主如何使用这些能力。
四层信任
| 层 | 关键问题 | 最低控制 |
|---|---|---|
| 来源 | 服务器是谁发布的 | 签名、固定版本、允许列表 |
| 能力 | 工具需要什么权限 | 只读优先、资源级授权 |
| 内容 | 返回值是否可信 | 来源标注、隔离、不可执行 |
| 副作用 | 失败后如何恢复 | 幂等、审计、补偿、回滚 |
任何一层缺失,模型都可能把外部数据误当成指令,或把一次失败重试变成重复副作用。
提示注入不是提示词问题
间接提示注入可以藏在网页、Issue、文档或代码注释里。模型看到的是拼接后的上下文,指令与数据的边界并不天然可靠。把所有工具输出都视为不可信输入,限制其可触发的动作,比要求模型“识别恶意内容”更可验证。
高风险动作应默认人工确认:删除数据、修改权限、转账、发布、发送外部消息。确认界面需要展示具体资源和后果,而不是只显示“是否继续”。
可恢复执行
写操作携带幂等键,执行层记录 before/after 与状态;总截止期到达时停止重试;每个工具声明最大重试数和是否可补偿。对无法回滚的副作用,宁可提前失败。
工具循环预算 可以观察步数、重试和幂等覆盖率如何改变风险暴露。它是相对比较工具,不是攻击成功率预测。
结论
MCP 让 Agent 更容易接入真实世界,也因此让权限设计成为核心工程。宿主必须把“模型能说什么”与“系统允许做什么”分开,用确定性控制包住不确定推理。
信任边界从哪里开始
一个工具调用链至少经过模型、宿主、协议客户端、远程服务器和真实资源五个位置。模型只输出一个“想调用”的结构化意图;真正执行的是宿主或服务器。安全设计不能把模型输出当作授权凭证,也不能假设远端服务器返回的文字天然可信。只要工具描述、网页、文件和消息可以进入上下文,它们就可能携带间接提示注入。
可以把一次调用拆成四个检查点:
| 检查点 | 需要回答的问题 | 控制手段 |
|---|---|---|
| 能力发现 | 这个服务器到底暴露了什么工具 | 固定工具清单、版本锁定、人工审核 schema |
| 参数构造 | 模型是否把不可信文本塞进了危险参数 | 参数类型、范围、路径与来源校验 |
| 执行授权 | 当前用户是否有权执行这个副作用 | 最小权限、短时令牌、二次确认 |
| 结果回流 | 返回内容是否会改变系统指令 | 标记为不可信数据、隔离渲染、内容过滤 |
MCP 规范描述的是通信与能力发现方式,不是一个自动安全沙箱。服务器和宿主仍然需要自己决定哪些工具可被发现、哪些调用需要用户批准、如何隔离凭据以及如何记录调用。协议标准化得越好,错误配置的影响面也可能越大。
工具不是函数签名的装饰
一个看似无害的 read_file(path) 工具,如果没有路径根目录限制,就能读取环境变量和私钥;一个 http_fetch(url) 工具,如果没有出口白名单,就能访问云元数据服务;一个 send_message 工具,如果没有幂等键,重试就会造成重复外发。模型是否“理解危险”不能替代参数验证和沙箱。
工具 schema 应明确:
- 允许的字符集、长度、枚举和数值范围;
- 资源 ID 是否由服务端解析,而不是由模型直接拼接路径;
- 是否产生副作用、是否可重试、是否需要人工确认;
- 超时、最大输出、最大调用次数和取消语义;
- 凭据作用域、过期时间和审计标识。
对写操作,优先让工具接受业务对象 ID,而不是接受任意 URL 或文件路径。由服务端根据 ID 解析资源,能把“路径穿越”和“越权访问”留在宿主层解决。
幂等、截止期与可回滚
工具循环常常把“失败”当成“可以再试”。但网络超时并不代表副作用没有发生,重试可能创建两个订单、发出两次通知,或重复删除数据。工程上需要三种结果状态:成功、失败、未知。未知状态不能自动重试,必须通过幂等键查询执行记录或交给用户处理。
建议把执行器设计成一个显式状态机:
- 生成调用 ID 与幂等键;
- 检查是否已有同一键的结果;
- 在总截止期内执行,并设置单步超时;
- 记录输入摘要、返回摘要和副作用;
- 失败时只重试声明为可重试且幂等的步骤;
- 到达截止期时返回可恢复状态,而不是无限循环。
沙箱可以限制代码、网络和文件系统,但它不能替代业务授权。即使工具运行在隔离容器里,容器仍可能访问挂载的密钥或外网。对于高风险动作,应该“默认拒绝 + 明确批准”,并在批准界面显示真实目标和不可逆后果。
如何评测和运营
Agent 安全评测不能只看任务成功率。应同时测量正常路径、错误路径和攻击路径:
- 工具超时、返回垃圾、部分成功和不支持的操作;
- 恶意网页或文档中的间接注入;
- 模型请求越权路径、超大输出或重复副作用;
- 用户撤销、网络断开和执行器重启;
- 审计日志是否足以还原“谁在何时让什么工具做了什么”。
MCP 让工具接入变得标准化,这是它的能力;真正的安全来自宿主在执行前后都保留控制权。模型负责提出计划,系统负责决定是否执行,审计负责说明发生了什么。 三者不能合并成一个“相信模型”的黑盒。
从威胁模型落到测试用例
审计一个 MCP 集成时,可以沿着“输入来自哪里、谁有权调用、执行器能做到什么、失败后留下什么”列测试。以下用例应该成为回归集的一部分:
| 场景 | 预期控制 | 失败时的危险信号 |
|---|---|---|
| 网页要求模型忽略系统提示 | 工具参数仍由宿主白名单校验 | 模型直接调用未知地址或读取敏感路径 |
| 工具返回“请执行下一步” | 返回值标记为数据而非指令 | 返回文本改变权限或工具清单 |
| 网络超时但请求已到达服务端 | 未知状态进入幂等查询 | 自动重试造成重复副作用 |
| 非白名单用户请求高权限工具 | 返回 403 并写审计 | 用客户端模型自述替代服务端鉴权 |
| 工具输出包含 HTML/Markdown | 按不可信内容渲染 | 脚本执行或链接伪装 |
这些测试不要求模型每次都被攻击成功,而是验证即使模型被诱导,确定性控制仍然守住边界。把它们做成自动化的故障注入,比在提示词里加一句“注意安全”更有效。
观测与运维
生产环境需要记录工具名、调用 ID、用户、权限决策、耗时、结果类别和副作用摘要,而不是完整保存所有敏感参数。对于写操作,审计要能回答“是否已经执行”和“能否补偿”;对于读操作,至少统计访问频率、输出大小和拒绝原因。Trace 中应将模型生成的意图与宿主批准的调用分开,避免把模型文本当成事实来源。
当工具升级或 schema 改变时,宿主应重新审核能力清单和参数约束,而不是自动接受服务器声明的新工具。对远程服务器,还需要固定版本、校验来源、限制返回大小和超时,并准备服务器不可用时的降级路径。MCP 的互操作性越强,越需要把“可发现”与“可信任”分开。
凭据也应有明确的生命周期。优先使用短期、按用户、按资源范围发放的令牌;不要把一个拥有全仓库写权限的令牌交给每个工具。令牌只在执行器内存中出现,日志只记录作用域和过期时间。用户撤销授权后,所有派生工具会话都应尽快失效。这样即使某个服务器被攻破,攻击者拿到的也只是有限、可追踪、可撤销的能力。
协议接入的测试应包含“服务器升级后工具行为改变”的场景。工具名、描述和 schema 可能变化,宿主不能因为版本号相同就假定语义不变。至少在发布前做能力清单 diff、参数 fuzz 和一个恶意返回值回归;对关键写操作保留人工审批与回滚脚本。
最后,给模型最小化的上下文:只暴露当前任务需要的工具和字段,不要把全部凭据、租户和内部路径一次性放进系统提示。能力越少,注入成功的收益越低,审计也越容易解释。安全边界不是靠更长的安全提示维持的,而是靠更小的能力集合和更硬的执行控制。
如果团队需要快速落地,可以先采用三层工具:只读查询、可逆写操作和高风险操作。只读工具允许自动调用并限制返回大小;可逆写操作需要幂等键、审计和补偿;高风险操作必须人工确认,并在界面上显示目标、范围和不可逆后果。这个分层比给每个工具都加一句“谨慎执行”更容易实现和测试。
用户撤销或权限变化时,执行器需要立即重新授权,而不是复用旧会话。工具调用链也应设置总预算和总截止期,防止服务器不断返回“还需要一步”把 Agent 留在循环里。只要能力、授权和截止期都能被执行器控制,模型被诱导的后果就能被限制在可解释的边界内。
最终验收可以只看四个问题:工具清单是否最小;参数是否由服务端解析和校验;写操作是否幂等且可审计;失败和撤销是否有明确恢复路径。四项都能给出证据时,Agent 才具备接入真实系统的资格。
把这些问题纳入发布清单,能让安全从一次性评审变成持续运行能力。
每次引入新工具时,先写清它读取什么、写入什么、失败后会留下什么,再决定是否需要人工确认。这个描述本身就能暴露多数权限设计错误。
工具越强,默认权限就应越窄;这两者必须同步增长。
权限设计与用户体验并不矛盾:清晰的确认信息和小范围能力反而能让用户更放心地授权。
这份信任应该由可验证的机制建立,而不是由界面文案索取。
- 01用户意图不可信输入
- 02模型计划概率输出
- 03MCP 客户端能力与授权
模型输出跨入执行域后,最小权限、幂等、沙箱和审计必须一起成立。
证据清单
来源与适用范围
- 规范
- 论文SWE-bench: Can Language Models Resolve Real-World GitHub Issues?
Jimenez et al. · 2024
- 论文
限定条件:基于 MCP 规范、SWE-bench 与提示注入研究的工程分析;不提供针对具体产品的攻击结论。