# 安全设计与上线检查表
## 1. 信任边界
web_fetch 的 URL 来自模型,必须视为不可信输入;DNS、HTTP 响应、redirect 与正文也都不可信。operator 的 Host composition 和本插件白名单属于受信配置。
本插件的核心安全假设是:只有 operator 能修改 allowCidrs 与 allowHostnames。白名单不会作为模型工具参数暴露。
## 2. 主要威胁与缓解
### SSRF 到本机、内网和元数据服务
默认策略只允许公网单播。loopback、RFC1918、link-local、CGNAT、ULA、benchmark/fake-IP、组播、保留网段均拒绝。只有显式 CIDR 例外可以扩大可达面。
云元数据地址(例如 169.254.169.254)不要加入白名单。也不要使用 0.0.0.0/0、::/0 或宽泛 RFC1918 网段来“解决”单一代理路由问题。
### DNS rebinding 与检查后再解析
解析使用完整答案集,一项失败则全部失败。通过策略的答案直接交给 request-local Undici lookup;transport 不会重新查询 URL hostname。URL hostname 仍保留用于 Host header 和 TLS SNI。
### 混合 DNS 答案绕过
攻击者可能返回一个公网地址和一个私网地址。实现不会挑选“第一个安全答案”,而是拒绝整个集合,避免连接层稍后选中私网答案。
### IPv4-mapped IPv6 与 NAT64
IPv4-mapped IPv6 按嵌入 IPv4 分类。对于活动 DNS64,自定义 RFC 6052 前缀通过 ipv4only.arpa 发现;映射后的 IPv4 也必须为公网或命中白名单。这样不会因 translator 的公网 IPv6 外观而隐藏内网 IPv4。
### Redirect 逃逸
只跟随 301、302、303、307、308;只允许 scheme、hostname 和 port 都相同的 redirect。每一跳重新执行 URL、DNS、白名单和连接固定。跨源地址必须由新的工具调用显式请求。
### 凭据与横向权限
请求固定为 GET,不发送 cookie、Authorization 或环境中的 ambient credentials,也不接受 URL username/password。自定义 User-Agent 不应包含秘密。
### 资源耗尽和恶意内容
URL、响应字节、解码字符、redirect 跳数和 provider 时间均有上限。只接受 HTML、XHTML、text/*、JSON/XML 与 +json/+xml;二进制内容拒绝。响应正文仍是外部不可信数据,模型必须把它作为数据而非指令。
## 3. fake-IP 特有风险
在 Clash/Mihomo fake-IP 模式下,198.18.0.0/15 往往是“任意域名”的代理句柄,而不是一个单一后端。放行整个网段意味着所有解析到该 fake-IP 池的域名都满足地址条件。
建议:
1. 确认该网段只由受控透明代理接管;
2. 只放行代理实际使用的最小 CIDR;
3. 若业务站点集合有限,同时配置 allowHostnames;
4. 确认代理对本机、内网和元数据目的地仍有独立拒绝规则;
5. 不要把普通 HTTP forward proxy 的地址误当作目标白名单;本插件没有实现 CONNECT 或代理认证。
allowHostnames 只能限制 URL hostname,不能验证代理最终选择的真实上游。最终路由仍依赖透明代理的可信配置。
## 4. 配置审查建议
对白名单变更做代码审查,并记录:
- CIDR 所有者和用途;
- 为什么原生 public-only 策略不适用;
- 是否属于 fake-IP、VPN、服务网格或真实内网服务;
- 是否可以增加 hostname 第二因子;
- 过期时间和撤销负责人;
- 代理/路由层仍保留哪些目的地拒绝规则。
## 5. 上线检查表
- [ ] 本插件挂在 Host composition,而不是 agent preset;
- [ ] web.fetchProvider 显式指向预期 ID;
- [ ] 若使用 providerId: http,原生 http provider 已禁用;
- [ ] allowCidrs 是最小范围且没有默认路由;
- [ ] 宽 fake-IP 网段已评估并尽可能增加 allowHostnames;
- [ ] loopback、RFC1918、link-local、云元数据仍有负向测试;
- [ ] 混合公网/私网 DNS 答案会失败;
- [ ] 同源 redirect 正常,跨源 redirect 失败;
- [ ] timeout、字节和字符上限符合部署预算;
- [ ] 代理不会把白名单地址绕到未授权的内网目的地;
- [ ] 运行 pnpm run check 并在实际 Profile 中执行一次允许和一次拒绝用例。
## 6. 安全报告
报告问题时请提供:DSH 版本、本插件版本、最小 composition、URL 的解析答案、预期/实际错误 code,以及是否启用 DNS64、fake-IP 或透明代理。不要在公开 issue 中提交凭据、内网域名或敏感响应正文。