安全实践
MCP 把 真实动作 交给模型去选。默认信任「能连上的 Server」是最常见的事故来源。本章只讲 防御侧 清单:审批、沙箱、白名单、供应链。不演示攻击手法。官方长文见 Security Best Practices 与 Authorization。
默认立场
把 MCP 想成 插件进程 + 网络身份。你批准的不是「一段 JSON」,而是一段将以你的用户身份跑在你机器上(或打到你的 API)的代码。
工具审批(人机协同)
Host 应在 UI 里展示:工具名、参数、目标 Server。你要养成的习惯:
- 读参数:路径是不是你以为的那一个目录?URL 是不是你的站点?
- 区分只读与有副作用的 Tool;后者保持 每次询问
- 不要为了「少点几次」对整个 Server 永久 Allow,除非它只有无害的只读工具
- 对话结束或换任务时,收回临时放大的权限
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 风格的思路(字段以产品为准):
实践建议:
- 生产 Agent:显式名单,拒绝名单外的
npx包 - 区分 用户级 与 项目级 配置;项目级可进 Git,用户级放 Token
- 远程 URL 同样进名单,避免对话里被诱导去连未知域名
供应链
npx -y @someone/mcp-whatever 与 pip install 一样,是在执行第三方代码。
远程 MCP 还有 OAuth 代理 风险:错误的同意屏幕或复用的 client id,可能让用户以为自己只授权了 A,实际令牌被用到别处。防御是:看清楚授权域名与 scope、关闭不需要的动态注册、按官方 Authorization 规范校验 issuer。不要跳过厂商的同意步骤。
Resource 与 Prompt 的数据面
- Resource 当 可公开给这个 Host 的文档 来设计,而不是「调试接口」
- 需要密钥时:Tool 去调 API,返回 脱敏后 的业务字段
- Prompt 模板不要拼接未审查的整页 HTML;当输入,不当指令注入源而不加隔离
现行规范把 Sampling 标为弃用,也减少了「Server 反向驱使 Host 调模型」的攻击面。新项目不要再实现 Sampling。
上线前短清单
- Inspector 里列出全部 Tools,删掉实验性写操作或改名标明
dangerous_* - Token 在环境里,权限可讲得清
- Host 对写操作是 ask,不是静默 allow
- 日志无密钥;Resource 无密钥
- README 写明允许的根目录与预期 Host