安全实践

MCP 把 真实动作 交给模型去选。默认信任「能连上的 Server」是最常见的事故来源。本章只讲 防御侧 清单:审批、沙箱、白名单、供应链。不演示攻击手法。官方长文见 Security Best PracticesAuthorization


默认立场

原则落地
只装可信 Server官方组织、你正在用的厂商、已审过的内部仓库
最小权限 Token只读优于读写;设过期;按仓库 / 按项目拆分
人要审批工具写文件、发邮件、付钱、改生产:默认问人
密钥不进 ResourceResource 经常被整段塞进上下文
配置不进 Git.cursor/mcp.json 可以提交命令,但不要提交 ghp_ / sk-

把 MCP 想成 插件进程 + 网络身份。你批准的不是「一段 JSON」,而是一段将以你的用户身份跑在你机器上(或打到你的 API)的代码。


工具审批(人机协同)

Host 应在 UI 里展示:工具名、参数、目标 Server。你要养成的习惯:

  1. 读参数:路径是不是你以为的那一个目录?URL 是不是你的站点?
  2. 区分只读与有副作用的 Tool;后者保持 每次询问
  3. 不要为了「少点几次」对整个 Server 永久 Allow,除非它只有无害的只读工具
  4. 对话结束或换任务时,收回临时放大的权限

OpenCode、Codex、Claude Code 都有各自的权限 / allowlist 语法,见对应课程。本课只要求:审批是功能,不是障碍


沙箱与文件系统

本地 Server 往往能读你给它的一切路径。

  • filesystem:根目录设到 allowed-notes,不要设到用户主目录
  • 自研 Server:用 Path.resolve() 后检查仍落在允许根下,拒绝 .. 逃逸
  • 浏览器 / Playwright:单独的配置文件,不要复用已登录生产的浏览器配置
  • 远程 HTTP Server:先只绑 127.0.0.1;对公网必须鉴权(官方建议 OAuth

Stdio 下 stdout 是协议线。日志去 stderr。不要把 Token 打进任何会被 Host 当上下文的字符串。


白名单(Host 侧)

当团队可以自己加 MCP 时,平台应限制「能跑哪些 Server」,而不是指望每个人都读完 README。

Codex 风格的思路(字段以产品为准):

allowed_mcp_servers = ["workshop", "filesystem"]

实践建议:

  • 生产 Agent:显式名单,拒绝名单外的 npx
  • 区分 用户级项目级 配置;项目级可进 Git,用户级放 Token
  • 远程 URL 同样进名单,避免对话里被诱导去连未知域名

供应链

npx -y @someone/mcp-whateverpip install 一样,是在执行第三方代码。

做法说明
钉版本避免每次 -y 都拉 latest
核对发布者@modelcontextprotocol/... 与仿冒作用域
少装每个额外 Server 都扩大工具面
内部镜像企业把允许的包镜像进私有 registry
审更新锁定文件变更要当依赖升级评审

远程 MCP 还有 OAuth 代理 风险:错误的同意屏幕或复用的 client id,可能让用户以为自己只授权了 A,实际令牌被用到别处。防御是:看清楚授权域名与 scope、关闭不需要的动态注册、按官方 Authorization 规范校验 issuer。不要跳过厂商的同意步骤。


Resource 与 Prompt 的数据面

  • Resource 当 可公开给这个 Host 的文档 来设计,而不是「调试接口」
  • 需要密钥时:Tool 去调 API,返回 脱敏后 的业务字段
  • Prompt 模板不要拼接未审查的整页 HTML;当输入,不当指令注入源而不加隔离

现行规范把 Sampling 标为弃用,也减少了「Server 反向驱使 Host 调模型」的攻击面。新项目不要再实现 Sampling。


上线前短清单

  1. Inspector 里列出全部 Tools,删掉实验性写操作或改名标明 dangerous_*
  2. Token 在环境里,权限可讲得清
  3. Host 对写操作是 ask,不是静默 allow
  4. 日志无密钥;Resource 无密钥
  5. README 写明允许的根目录与预期 Host

下一步

评论