连接器出口防护(SSRF 防御)
父节点:connector
一旦 owner 可以上传任意的 OpenAPI connector,目标 URL 就变成了攻击者可控的——这是典型的 SSRF 攻击面(把它指向 169.254.169.254 或某个内部服务)。防御分两层:
- 装配期(静态): 每个 spec 的
servers[].url和 OAuth 的tokenUrl都会被检查;回环地址 / RFC1918 私网地址 / ULA / 链路本地地址一律被拒绝,在 connector 能被使用之前就被挡下。 - 运行期(动态): 一个自定义 dialer 会在每一次 DNS 解析时重新检查解析出的 IP 是否为公网地址,并阻止指向私网地址的 3xx 重定向——以此挫败 DNS rebinding(域名在检查时解析为公网地址,在实际调用时却解析为私网地址)。一个白名单(
CONNECTOR_EGRESS_ALLOW)为 e2e / mock 场景放行特定主机名。
值得记住的两轴对比
两条 plugin 轴线得到的是相反的隔离方式,因为它们的需求本来就相反:
| 轴线 | 需要网络吗? | 隔离方式 |
|---|---|---|
| mcp-capability-plugins / sandbox-js-hardening | 不需要 | 把网络整个关起来(--unshare-net) |
| OpenAPI connector | 需要(要调用 SaaS) | 放它出去,但出口被过滤(egress guard) |
关进笼子 vs 过滤出口:当不受信任的代码必须对外发起请求时,你不能靠拿掉网络来做隔离——你只能靠控制出口来做隔离。同样的直觉(不受信任的代码只能通过一条窄的、声明式的通道触达宿主),两种不同的机制。