安全设计 · Runtime 网络

Runtime 出站 URL 与 SSRF 防护

证据快照:2026-08-12,Runtime 实现截至 Task 10 整合修复(Task 1–8 基点 80c377fa)。本文依次介绍 OpenProgram 现状、其他项目和 OpenProgram 后续计划;实现行为与未来工作分别标注。

第一部分 · 当前
OpenProgram 当前状态

Runtime 拥有的 HTTP 请求使用注册表键控 URL 策略和托管传输。实现验证全部 DNS 结果,只连接批准的 peer,显式处理重定向,将凭据限制在声明的 origin,限制响应资源,并在发现未分类使用方或活动非托管 SDK 传输时使静态验证失败。

01已实现边界

组件已实现职责明确不负责
openprogram/security/url_policy.pyURL/origin 规范化;scheme、userinfo、host、port 验证;全部 A/AAAA 分类;精确 owner 例外;稳定脱敏 reason code不发送网络请求,不推断调用方信任类别
openprogram/security/safe_http.py不可变的 42 使用方注册表;同步/异步 peer 约束传输;保留 Host/SNI;手动重定向;凭据、header、MIME、解码正文、编码、超时、代理及原子下载约束不接受调用方创建的策略对象,不暴露 verify=False
使用方 adapter选择一个不可变注册键;配置服务或回调还提供 owner 配置的精确 origin不得另写私网地址分类器或通过原始客户端重试
runtime_http_audit.py, doctor以及 scripts/check_runtime_http.py有界脱敏拒绝状态、精确 owner 例外/代理报告、AST 清单、SDK 处置验证和过期排除检测不显示 userinfo、query、fragment、凭据、peer 响应正文或含 token 的路径

02Runtime 使用方与独立边界

边界当前处理本功能中的状态
任意及派生 Runtime URLweb_fetch、附件、生成资产、图片结果下载、目录、市场和更新元数据使用公共或精确服务策略的托管客户端纳入
固定/配置 API网页搜索、图片 API、channel REST、TTS、provider 列表/探测/OAuth、Web 模型列表、MCP HTTP/SSE 和本地探测使用固定或 owner 配置的精确 origin纳入
第三方 SDKProvider/MCP 客户端注入托管传输;精确 origin REST adapter 保持托管;无法注入的 Bedrock、Slack/Discord gateway 和 edge-tts SDK 路径关闭失败纳入并分类
浏览器导航、popup、Service Worker 和子资源由浏览器控制设计及 owner 出站隔离管理排除
沙箱任意代码、插件代码、外部 provider CLI 和包管理器由沙箱、插件信任、子进程和安装边界管理排除
Owner 控制面存活探测仅 loopback 的有限排除按精确调用类型、owner、原因和数量列入清单已分类,不宣称属于 Runtime URL fetch
功能矩阵范围与状态。 已实现控制仅覆盖 Runtime 拥有的 HTTP fetch。在整合仓库门禁通过后,矩阵对该限定功能记录 ◐ 。浏览器、任意代码、插件、外部 CLI 和包管理器子进程仍是独立边界。
第二部分 · 参考
其他项目如何设计此边界

比较保留功能矩阵全部十二个外部列及 OWASP。权限提示、hostname 规则、应用 URL 验证、策略代理和操作系统网络沙箱是不同控制;上游包装器和协议库不重复计为独立实现。

03参考机制

证据边界。 矩阵使用固定快照。当前官方文档直接链接作为设计背景,不反向修改固定版本分数。快照中未确认的能力标为未确认,不宣称普遍不存在。
项目应用 URL fetch 证据网络或权限边界采用、调整或拒绝
Hermes共享 url_safety 覆盖 Web、浏览器、vision 和 gateway media。DNS 失败关闭;拒绝 loopback、RFC1918、link-local、CGNAT、metadata、reserved、multicast 和 unspecified 结果;逐跳检查重定向;URL 脱敏,媒体流式处理且有限额。进程级 allow_private_urls 开关同时放宽多个入口。应用检查仍不能替代操作系统网络隔离。采用共享失败关闭验证、完整地址集、重定向检查、脱敏与限额。将全局开关改为精确使用方范围内的服务 origin 例外。
OpenClaw默认拒绝私有、内部和特殊用途目标,支持精确/通配 hostname 例外,并在导航、交互引发加载及最终 URL 处检查。文档指出推测导航和浏览器子资源风险。官方文档说明请求拦截不是网络防火墙:重定向、popup、Service Worker 和后台资源仍可能需要出站隔离或策略代理。采用严格默认值和显式例外。浏览器拦截作为独立验收边界,不计为 Runtime fetch 证据。
Claude CodeWebFetch(domain:...) 支持 allow/deny。请求前将 hostname 发到 Anthropic 安全阻止列表,结果缓存精确五分钟;owner 可禁用 preflight。Bash 沙箱使用子进程继承的 Seatbelt/bubblewrap HTTP/SOCKS 代理。代理信任客户端 hostname 且不检查 TLS 内容,因此宽泛域名和 domain fronting 仍有风险。采用分层工具授权和子进程出站策略;不将 hostname 权限视为 DNS/IP/连接时 SSRF 证据。
Codex审计的主线不以一条 WebFetch 字符串检查替代网络边界。codex-network-proxy 提供 HTTP/SOCKS5 代理、精确/受限通配域、私网解析拒绝、有限只读方法、MITM header hook、Unix socket 控制和结构化审计;操作系统沙箱限制 loopback 绕过。采用结构化拒绝原因、审计和托管策略;保留了解使用方的 Runtime 安全客户端,不只依赖子进程代理。
CodeBuddy 2.109.3WebFetch 应用安全中心域名策略,拒绝 IP 字面值、 localhost和部分私有范围。企业微信媒体使用官方 CDN allowlist,禁用重定向。沙箱 allowedDomains 与 WebFetch 权限取交集。审计 bundle 的普通 WebFetch 只检查 host 字面值;快照未确认完整 hostname A/AAAA、peer 绑定或逐跳重定向约束。采用固定 channel 服务 allowlist 和权限/网络策略交集;拒绝普通 fetch 仅保护 IP 字面值。
Gemini CLI官方工具文档警告 web_fetch 能访问 localhost/私网;Plan Mode 可要求确认。本地 0.35.3 core 含 IP 分类与 DNS 工具,但该警告表明它们不构成通用 WebFetch 私网边界。用户确认是权限决策,不限制实际连接 peer。采用明确风险文档;拒绝以确认替代确定性目标约束。
OpenCodewebfetch 权限使用完整请求 URL,支持 allow、ask、deny。当前官方权限文档不能证明私网 IP 分类、完整 DNS、逐跳重定向或 peer 绑定。shell 使用主机用户网络权限;官方说明字符串规则是尽力处理,不是网络隔离。采用统一资源权限语义;获准 URL 仍必须通过独立传输策略。
pi-mono固定快照未确认核心产品内置任意 URL fetch;网络能力主要来自 shell、安装器或用户扩展。核心快照未确认 OS 出站策略;第三方 pi-sandbox 不计为内置 pi-mono 行为。不作为 Runtime SSRF 算法参考;扩展边界支持将第三方代码排除在安全客户端完成范围外。
pi-ai这是协议参考源码,不是可运行产品,没有 session 或 Runtime URL 使用方。不适用。排除产品级 SSRF 结论,但保留矩阵列以维护审计单位区别。
weclaw固定快照是到外部 ACP/CLI Agent 的消息桥接,未确认独立通用 URL fetch。主要继承启动 CLI 的工具和网络权限;不将受委托产品的控制重复算给 weclaw。保留 channel media 和外部进程启动作为相关边界;不作为通用安全 HTTP 参考。
cc-internal / cx-internal / gm-internalcc-internal 和 cx-internal 包装上游启动器; gm-internal 大量复用 Gemini CLI。审计包未确认独立加强通用 URL fetch 策略。继承大部分 Claude Code、Codex 或 Gemini CLI 的权限和网络行为。增加认证或 endpoint 本身不构成 SSRF 边界。仅审计其新增 endpoint、凭据转发和配置差异;不重复计算为三个独立安全设计。
OWASP区分已知服务 allowlist 与任意公共目标验证,限制协议,验证全部 A/AAAA,可信服务优先使用 allowlist。单次 DNS preflight 仍有 DNS pinning 和检查/使用时差风险,因此也建议网络控制。采用独立信任类别和连接时 peer 约束;拒绝只靠单个 preflight DNS 结果。

一手来源: Hermes url_safety.py, Hermes 安全, OpenClaw 安全, Claude Code 沙箱, Claude Code WebFetch 安全检查, Codex 网络代理, OpenCode 权限, Gemini CLI 工具以及 OWASP SSRF 防护.

固定版本本地快照证据: @tencent-ai/codebuddy-code@2.109.3 dist/codebuddy.js, CHANGELOG.md, dist/web-ui/docs/cn/cli/permissions.md; @google/gemini-cli@0.35.3 core/dist/src/utils/fetch.js; references/pi-mono@3eb002766fff; references/weclaw@10711d0c6b7e;以及 references/pi-ai.

04采用、调整与拒绝的选择

决策机制原因
采用一个纯 URL/IP 策略;全部 DNS 地址通过;DNS 失败关闭;每次重定向重新判断;错误只含 origin;限制解码正文统一覆盖 Runtime 的目标、重定向、凭据与资源边界。
采用区分不可信公共、固定公共服务、配置服务及 loopback 回调四种信任类别保留 owner 配置的 localhost/私网服务可用性,不给任意公共使用方私网权限。
采用Claude Code/CodeBuddy 权限与网络分层、Codex 结构化拒绝原因、CodeBuddy 固定 channel media allowlist权限回答谁可请求资源;传输策略回答哪个 peer 接收连接与凭据。
调整Hermes 进程级 allow_private_urls替换为精确使用方加规范 origin 或规范私有/本地 CIDR;metadata 和 link-local 仍不可例外。
调整OpenClaw 浏览器拦截与 Codex 全进程出站代理浏览器控制保持独立门禁;策略代理是可选、owner 声明、独立 peer 约束且 doctor 可见,不允许直接 fallback。
拒绝仅 URL 字符串检查、单次 DNS preflight、隐式重定向、继承环境代理、禁用 TLS 验证或原始客户端 fallback每项都留下目标、重绑定、凭据或绕过路径。
拒绝以用户确认或 hostname allow/deny 实现目标约束两者均不验证全部解析地址,也不约束连接 peer。
拒绝对所有 HTTP 客户端实施仅公共目标规则这会破坏显式配置的本地模型 endpoint、MCP server 和内网服务。
拒绝将 Origin/Host、CORS、owner 认证、浏览器检查或沙箱网络算作 Runtime SSRF 完成这些控制保护不同方向或执行边界。
第三部分 · 计划
OpenProgram 计划状态与后续工作

Runtime URL fetch 截至 Task 8 已完成。本节先记录实现证据,再列独立后续边界。矩阵保持 ◐ ,因为这些独立边界不在范围内。

05已完成计划:实现证据

以注册表键标识的调用方

42 个不可变使用方
四种信任类别
精确配置或回调 origin
›

纯策略决策

规范 URL 和 origin
一组完整 DNS 结果
精确例外与 reason code
›

托管传输

批准的 IP peer
原始 Host、SNI 和证书
手动重定向与有界响应

05.1 传输与策略行为

05.2 使用方与 SDK 处置证据

处置使用方约束
注入传输provider.openai.sdk, provider.anthropic.sdk, provider.google.sdk, mcp.configured.http, mcp.configured.sse公开 SDK 构造接收限定范围的托管客户端或工厂;真实 SDK 链测试到达受约束 backend。
精确 originTelegram、WeChat、Feishu、Matrix、Slack、Discord、固定/配置 TTS 和其他固定/配置 REST 使用方附加凭据前冻结规范 owner/随附 origin;重定向不能把凭据转到其他 origin。
派生 URL 提取附件、生成资产和图片结果使用方SDK/上游响应提供 URL,随后 Runtime 通过专用托管注册使用方下载或上传。
禁用provider.amazon_bedrock.sdk, channel.slack.gateway_sdk, channel.discord.gateway_sdk, tts.edge_sdk启动或调用以 UNMANAGED_TRANSPORT 失败,发生在导入/使用无法注入网络 SDK 前。Bedrock 同时覆盖注册 stream 和模型列表入口,早于 boto3/botocore 凭据或客户端活动。

05.3 Owner 例外、策略代理、doctor 和清单

Owner 配置只接受注册使用方加一个规范 origin 或规范私有/本地 CIDR。拒绝通配、后缀、凭据、未知字段、公共/默认路由网段、metadata、link-local 和使用方不允许的例外形式。既有 owner 认证设置路径是唯一变更权限。

只有 owner 配置设置 enforces_target_policy: true才可用策略代理。Runtime 先判断目标,独立约束代理 peer,通过 doctor/audit 报告委托,绝不直接重试。

清单排除Owner 与限定原因
security/safe_http.pyRuntime 托管传输;唯一允许的直接 httpcore pool/proxy 构造
programs/tools/web/browser/_chrome_bootstrap.py浏览器控制;精确 browser opener 构造和 loopback CDP 存活连接
cli/commands/mcp.pyOwner 控制面;仅认证 backend opener
cli/ink.py, cli/commands/doctor.py, cli/commands/rescue.pyOwner 控制面;仅精确 loopback worker 存活 socket

未注册 raw 调用、活动非托管 SDK、没有分类使用方的注册项或过期排除均使检查失败。Doctor 暴露稳定的 runtime-http-registry, runtime-http-owner-exceptions, runtime-http-policy-proxy, runtime-http-recent-denials以及 runtime-http-unmanaged-transport 标签。

05.4 验证快照

命令记录结果
uv run --extra dev pytest -q tests/security804 passed
uv run --with pip --with boto3 pytest -q tests/meta_functions tests/providers tests/unit tests/webui tests/integration/programs/test_mcp_client.py3482 passed, 12 skipped, 1 xfailed
uv run --extra dev --with boto3 pytest -q4923 passed, 14 skipped, 2 deselected, 1 xfailed
uv run python scripts/check_runtime_http.pyunregistered=0 active_unmanaged=0 registry_without_consumer=0 stale_exclusions=0
uv run python scripts/check_feature_matrix.py docs/reference/design/feature-matrix.htmlfeatures=160 openprogram_score=78 openprogram_gaps=73 openprogram_only=6
发布门禁。 已具备策略解析/地址测试、真实同步/异步 socket/TLS peer 测试、DNS 重绑定防护、重定向/凭据 origin 测试、响应/解压/超时清理、全使用方迁移、四类 SDK 处置且零活动非托管传输、仅 owner 精确例外、doctor/audit/静态约束和 42 行兼容合同。声明 dev 与可选 provider 依赖后,完整仓库命令通过。功能矩阵记录 ◐ ,因为验证范围是 Runtime 拥有的 HTTP,不包括独立浏览器、任意代码、插件、外部 CLI 和包管理器边界。

06OpenProgram 后续计划

后续边界宣称完成前必需工作
浏览器导航及页面派生流量为每个 backend 定义/测试导航、popup、Service Worker、后台资源、重定向、下载、CDP 和浏览器 profile 策略;拦截不足时使用强制出站边界。
插件与任意代码网络信任/沙箱模型与 Runtime 安全 HTTP 独立;如需限制这些进程网络,增加 OS 或策略代理出站边界。
禁用的第三方 SDK 网络功能仅在 SDK 支持托管传输注入或 owner 强制策略代理具有同等测试后启用;不得用未验证 SDK 保证替代禁用处置。

相关文档: 沙箱设计, 网络代理设计以及 功能矩阵.