那些你的团队遗忘在后台且正使用生产环境凭据运行的 MCP 服务器
周一,一位新工程师加入了团队。到周三时,她已经搭建好了本地 Agent 环境:一个桥接到公司部署 API 的 MCP 服务,指向 Staging 环境,并与她的编辑器相连。入职文档引导她完成了 OAuth 流程。她粘贴到服务器环境文件中的令牌是同事发给她的——这与 CI 流水线用于发布到 Staging 环境的是同一个令牌。到周五,她已在共享办公空间与团队一起进行协作开发。
MCP 服务仍在运行。绑定在 127.0.0.1。无需身份验证。令牌已加载到进程中。她没多想,因为她并没在使用它。但那天访问任何网站的任何标签页,都可以通过她自己的浏览器与她的本地服务通信。共享办公空间 Wi-Fi 上的任何其他笔记本电脑也同样可以,因为她没注意到该服务实际上绑定到了 0.0.0.0。你的 CI 流水线用来推送到 Staging 的 OAuth 令牌,现在任何能诱导浏览器向本地 IP 发起请求的人都能触及——在 2026 年,这只需要一个弹窗。
本文讨论的就是这类故障:“我在笔记本上开发”与“我的笔记本是对手可以触及的服务器”之间的鸿沟。MCP 服务在设计上恰好处于这个鸿沟之中。大多数团队尚未察觉。
不再适用的心智模型
工程师们在 localhost 上运行程序已经三十年了。潜意识里的假设总是一样的:localhost 意味着你,且仅代表你。如果你将开发服务器绑定到 8080 端口,唯一能与之通信的是你笔记本上的另一个程序,而你笔记本上唯一的程序就是你选择运行的程序。
在 MCP 出现之前,这个模型就已经错了。当 Web 框架引入暴露源码映射(source maps)的热重载服务器时,它错了。当 Docker Desktop 为了方便而打开守护进程端口时,它也错了。但 MCP 让这种错误在操作层面上变得有趣起来,因为 MCP 服务不是被动资源——它们是 RPC 端点,其核心意义在于代表用户使用用户的凭据行事。
一旦你安装了带有真实令牌的 MCP 服务,以下三件事就会改变你的威胁模型:
第一,服务器现在持有一个授予生产相关访问权限的凭据。即使你告诉自己这“只是 Staging 环境”,通常相同的 OAuth 客户端也是针对相同的身份提供者配置的,拥有相同的刷新令牌链,以及 CI 流水线所使用的相同作用域(scopes)。你 dotfile 文件中的令牌不是沙盒——它是你团队的部署密钥。
第二,服务器是一个 HTTP 端点,或者桥接到了一个端点。MCP STDIO 传输在设计上是本地的,但 mcp-remote、MCP Inspector 以及数十个社区代理很乐意为 STDIO 服务套上 HTTP 接口,以便编辑器和基于浏览器的客户端可以连接。由于“这只是 localhost”,在许多发行版本中,这个 HTTP 接口默认不进行身份验证。参见上文了解为什么这句话已经失去了意义。
第三,浏览器现在成为了威胁面的一部分,这种方式是以前(比如你的 Postgres 开发实例)从未有过的。Postgres 不说 HTTP。MCP HTTP 桥接器会说。任何加载了 JavaScript 的标签页都可以尝试向 http://127.0.0.1:8765 发起 fetch(),并且——在合适的条件下——获取带有你真实数据的 200 响应。
DNS 重绑定不再仅仅是假设
使上述攻击成为现实的技术是 DNS 重绑定(DNS rebinding),现在需要认真对待它的原因是,MCP SDK 生态系统在 2025 年到 2026 年期间一直在披露并修复其相关版本。
攻击之所以奏效,是因为浏览器中有两项安全检查,且它们发生在不同时间。当 attacker.example 上的脚本尝试调用 attacker.example/api 时,浏览器的同源策略(Same-origin policy)是允许的。DNS 查询返回攻击者的真实 IP。连接成功。到目前为止,完全正常。
现在,攻击者的 DNS 服务器改变了主意。下次浏览器查找 attacker.example 时,它会得到 127.0.0.1。从浏览器的角度来看,脚本仍在调用 attacker.example/api——这始终是同一个源。同源策略不会重新评估。然而,TCP 连接现在降落在了开发者的本地机器上。MCP 服务只检查请求是否来自浏览器,于是便做出了回复。
Anthropic TypeScript SDK 在 1.24.0 版本中发布了默认开启的 Host 标头检查,专门为了堵住这个漏洞。Python SDK 在 1.23.0 中发布了同 等功能。任何旧版本——包括大量 2025 年初创建的 lockfile 中固定的版本——都接受 Host 标头被设置为攻击者想要的任何内容的请求,而这正是整个攻击的核心。微软的 Playwright MCP 服务针对同类漏洞也有一个单独的 CVE,它让恶意标签页能拥有一套运行在开发者会话 cookie 下的完整浏览器自动化工具包。
缓解措施列表简短且乏味:
- 更新 MCP SDK 到默认强制执行 Host 标头验证的版本。
- 明确绑定到
127.0.0.1。永远不要在开发机器上绑定到0.0.0.0,绝对不要。 - 在每个 MCP HTTP 端点上都要求身份验证,即使是在 localhost 上。这是大多数团队会跳过的部分,因为觉得对于开发工具来说太繁琐了。
- 如果你运营公司 DNS 解析器,请将其配置为丢弃将外部域名解析为 RFC1918 地址的响应。
- https://rafter.so/blog/mcp-dns-rebinding-localhost
- https://authzed.com/blog/timeline-mcp-breaches
- https://www.obsidiansecurity.com/blog/when-mcp-meets-oauth-common-pitfalls-leading-to-one-click-account-takeover
- https://aembit.io/blog/the-ultimate-guide-to-mcp-security-vulnerabilities/
- https://www.oligo.security/blog/critical-rce-vulnerability-in-anthropic-mcp-inspector-cve-2025-49596
- https://github.com/modelcontextprotocol/typescript-sdk/security/advisories/GHSA-w48q-cv73-mx4w
- https://www.varonis.com/blog/model-context-protocol-dns-rebind-attack
- https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices
- https://www.docker.com/blog/mpc-horror-stories-cve-2025-49596-local-host-breach/
- https://vulnerablemcp.info/vuln/cve-2025-66414-66416-dns-rebinding-mcp-sdks.html
