MCP Apps 默认安全设计:为什么“不声明即禁止“是嵌入AI聊天UI的终极答案?
2026/9/18 22:04:15 网站建设 项目流程

MCP Apps 默认安全设计:为什么"不声明即禁止"是嵌入AI聊天UI的终极答案?

【免费下载链接】ext-appsOfficial repo for spec & SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers项目地址: https://gitcode.com/GitHub_Trending/ex/ext-apps

MCP Apps 是 Model Context Protocol(MCP)的官方扩展协议与 SDK,让 MCP 服务器能够向 AI 聊天应用(如 Claude、ChatGPT)内嵌交互式 UI。它的核心安全理念是默认安全设计:不声明即禁止——应用每一点网络访问、每一项设备权限,都必须预先显式声明,否则一律被宿主(Host)拒绝。本文将带你快速理解这套连接策略的价值。

为什么"不声明即禁止"如此重要

当 AI 聊天客户端嵌入来自各个 MCP 服务器的 UI 时,它面对的其实是不可信的内容。官方规范明确列出了威胁模型:恶意服务器投递有害 HTML、被攻破的 UI 尝试逃逸沙箱、UI 未授权调用工具、UI 外泄宿主敏感数据、钓鱼与社会工程攻击。

应对方式不是"事后拦截",而是默认拒绝(deny by default)

  • 未声明域名的网络请求 → 直接被 Content Security Policy(CSP)阻断
  • 未声明的设备权限(摄像头、麦克风、地理位置)→ iframe 的allow属性中不存在,浏览器层面就拒绝
  • 未完成的 OAuth 授权 → 受保护工具直接返回401,请求根本到不了业务逻辑

这种策略的价值在于:安全边界由声明决定,而非由开发者"记得写拦截代码"决定。漏写的代码是漏洞,漏写的声明只是功能缺失——后者远比前者安全。

四层安全架构:从规范中看实现

1. 强制 Iframe 沙箱

规范要求:所有 View 内容MUST(必须)渲染在带受限权限的沙箱 iframe 中,所有与宿主的通信都走postMessage且由宿主掌控。双 iframe 结构(Sandbox Proxy + 内层 iframe)进一步隔离了不可信 HTML。参考宿主实现可见于 examples/basic-host/src/sandbox.ts。

2. 默认全拒绝的 CSP 构建

这是"不声明即禁止"最直接的体现。规范中宿主构建 CSP 的模板以default-src 'none'开头,每一项资源都只有两类来源:'self'或你在元数据里显式声明的域名:

default-src 'none'; connect-src 'self' /* + connectDomains */ frame-src 'none' /* 除非声明 frameDomains */ object-src 'none';

关键安全要求写在规范 Security Implications 一节(specification/2026-01-26/apps.mdx):

Host MUST block connections to undeclared domains—— 宿主必须阻断到未声明域名的连接。

也就是说,你的应用不填connectDomains,就一次外部请求也发不出去。

3. 设备权限同样"未声明即禁用"

permissions元数据映射到 iframe 的allow属性:只有声明了camera才推入camera,声明了microphone才允许麦克风。没写 = 没有权限,浏览器直接拒绝调用。

4. 可审计的双向通信

所有 View 到宿主的通信都走可审计的 MCP JSON-RPC 消息,宿主验证每一条入站消息、拒绝畸形类型、并可记录 UI 发起的 RPC 调用用于安全审查。通信层 SDK 见 src/app-bridge.ts。

实操指南:如何声明应用需要的连接域名

如果你的 MCP App 需要调用外部 API,在 UI 资源的_meta.ui.csp中声明即可(详见 docs/csp-cors.md):

_meta: { ui: { csp: { connectDomains: ["https://api.example.com"], // fetch/XHR/WebSocket }, domain: APP_DOMAIN, // 可选:给 API 服务器的稳定 Origin,用于 CORS 白名单 }, }

两个容易踩的坑:

  1. 开发环境的localhost也要声明——本地调试时同样适用"不声明即禁止"
  2. 公网 API 若返回Access-Control-Allow-Origin: *或使用 API Key 认证,则无需配置domain;只有需要 CORS 白名单的 API 才需要稳定 Origin

完整配置示例可参考 examples/sheet-music-server 与 examples/map-server。

进阶:用 OAuth 为工具加锁

"不声明即禁止"不止用于网络,也延伸到授权。MCP Apps 支持两种模式(详见 docs/authorization.md):

模式行为适用场景
按服务器授权连接即校验,所有请求必须携带有效 Token全部工具都敏感
按工具授权仅受保护工具触发 OAuth 流程,公共工具直接放行公共/敏感工具混合

更精妙的模式是UI 发起的授权升级:应用先以公共数据加载(无登录墙),用户点击敏感操作时,宿主才透明地完成 OAuth 流程并带 Token 重试。体验快,安全边界清晰。

如何验证:端到端安全测试

仓库内置了 Playwright 安全测试 tests/e2e/security.spec.ts,对真实运行的示例服务器验证沙箱与权限行为,可作为你自己宿主实现的安全基线参考。

总结:默认拒绝带来的三重收益

  1. 对宿主开发者:安全逻辑收敛为一条规则——"元数据没写的,一律拒绝",无需为每个应用写拦截代码
  2. 对应用开发者:安全声明集中在资源元数据一处,声明即文档,边界一目了然
  3. 对最终用户:嵌入在 AI 对话中的 UI 被限制在一个最小权限的沙箱里,即使服务器被攻破,攻击面也被 CSP + 沙箱 + 权限白名单层层封死

想动手体验?按 docs/quickstart.md 克隆仓库后执行npm install && npm start(仓库地址:git clone https://gitcode.com/GitHub_Trending/ex/ext-apps),打开 http://localhost:8080/ 即可在参考宿主中浏览全部示例。

【免费下载链接】ext-appsOfficial repo for spec & SDK of MCP Apps protocol - standard for UIs embedded AI chatbots, served by MCP servers项目地址: https://gitcode.com/GitHub_Trending/ex/ext-apps

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询