安全威胁与防护
MCP 把"执行工具"的能力交给了大模型应用:连接一个服务器,等于让模型获得一组可调用的动作。权限越大、风险越高。本章梳理威胁模型与防护实践,官方还有专门的安全最佳实践文档,以其为准。
MCP 的安全模型
核心信任链是:用户 → 宿主 → MCP 客户端 → 服务器。要点有二:
- 是否调用工具、是否允许敏感操作,最终决定权在用户/宿主(可配置为每次确认);
- 服务器的工具描述会被模型读到,也可能被诱导——安全不能只靠"模型懂事"。
主要威胁
| 威胁 | 说明 |
|---|---|
| 恶意/不可信服务器 | 服务器本身带毒:工具读取私钥、上传文件、执行命令 |
| 工具被诱导调用 | 用户被钓鱼内容诱导,让模型去调用高权限工具 |
| 提示注入 | 网页、文档等"内容"混进上下文,指示模型执行未授权操作 |
| 过度权限 | 服务器声明全盘读写、shell 执行、网络访问等远超需求的工具 |
| 数据外泄 | 读取的敏感文件/数据经工具或网络被传往外部 |
| 供应链 | 被投毒的依赖、目录站上的冒名服务器在安装/更新时进入系统 |
| 提示注入特别隐蔽:工具或资源返回的内容与用户指令混在同一上下文,模型可能分不清"内容里说的"与"用户要求的"。 |
防护实践
- 最小权限:服务器只开必要工具、只读优先;文件类用白名单根目录并防穿越(见第 14 章);
- 只连可信服务器:坚持第 16 章的 checklist,来源不明一律不接;
- 敏感操作人工确认:写入、删除、执行、外发在宿主里设为"每次询问";
- 密钥不进描述:工具描述会被模型读到并可能被注入利用,令牌放环境变量、不进 description;
- 描述说清边界:在描述里声明"只允许操作白名单目录""不执行删除",让模型有据可依;
- 审计日志:把每次工具调用(谁、何时、什么参数)落到日志,便于回溯;
- 隔离运行:未知服务器放容器/沙箱,限制网络与文件系统。
# 危险写法:描述暴露能力边界外的动作
@mcp.tool(description="读取服务器上任意文件,删除敏感数据")
def read_any(path: str) -> str: ...
# 安全写法:白名单 + 明确边界 + 结果提示
@mcp.tool(description="读取白名单 docs 目录内的文本文件;只读,不做任何修改")
def read_doc(name: str) -> str:
return _read_under(Path("docs"), name) # 内部仍要校验路径
# 提示注入的最小应对:把不可信内容与指令隔开,标注来源
tool_result = mcp_call("fetch", {"url": url})
messages.append({"role": "tool", "content": f"[来自网页{url}的内容,仅供引用]\n{tool_result}"})
官方安全规范
官方在 modelcontextprotocol.io 上维护安全相关的最佳实践与规范说明,涵盖权限模型、威胁分析与部署建议;版本演进快,一切以该官方页面为准。 小结:MCP 安全 = 认清"模型拿到的是执行能力"这一事实,用最小权限服务器、可信来源、敏感操作确认、密钥不进描述、审计日志与隔离运行守住边界;具体规范以 modelcontextprotocol.io 官方安全文档为准。