配置禁止重定向,为何请求仍继续?Axios Fetch 适配器的安全契约
一、背景与时间线
官方确认Fetch适配器未执行maxRedirects限制,底层默认跟随跳转;HTTP适配器不受这一具体问题影响。利用需要可控跳转源及依赖该配置的应用,不能称为无条件SSRF。项目9月16日披露、NVD9月28日记录、GitHub9月30日审核收录。修复建议为1.20.0及以上。版本表仅列1.17.0,但正文还记录1.18.1验证结果,因此不能把未列出的邻近版本自动判为安全。
以上事实依据项目安全公告。这里的披露或数据库收录日期不是攻击发生时间。本次核验的一手来源没有确认在野利用,本文不据此断言不存在攻击。
二、影响范围与版本边界
| 项目 | 核验结果 |
|---|---|
| 公告标识 | GHSA-r4gj-5m52-g5wh |
| 项目公告日期 | 2026-09-16 |
| 受影响版本 | 公告版本表列1.17.0,正文还验证了1.18.1 |
| 修复版本 | >=1.20.0 |
| 事件性质 | 漏洞披露或近期数据库收录,非已确认攻击事件 |
版本信息应结合实际运行环境判断。依赖清单命中仅是第一步,还需要确认调用路径、配置和不可信输入能否到达相应逻辑。发行商回补补丁的情况,应核对其安全公告和构建证据,不能只按上游版本字符串做最终判断。
三、技术原理与工程分析
配置进入公共API之后,还要经过适配器映射,再进入运行时。安全属性必须穿过全部三层才能生效。若适配器忽略字段,调用成功不意味着约束执行成功;它甚至可能制造一种非常稳定的错误结果,使普通可用性测试全部通过。
工程分析:只校验首次URL时,程序批准的是第一跳。运行时若自动访问第二跳,批准对象已经改变。是否泄露响应、是否触发内部状态变更,取决于出站可达性、目标认证和应用如何处理结果,不能从库漏洞直接推出云账号被接管。
建议对“禁止跳转”建立可观测契约:发出首个请求后收到3xx,应停止或返回待处理结果;不能静默发出下一次请求。若业务允许跳转,每一跳重新验证目的地,并设置跳数、超时和响应大小预算。手动模式也不授权应用无条件读取Location后继续请求。
四、防御性安全示例
以下Python 3示例只演示安全不变量,不连接网络、不执行外部程序、不生成真实利用载荷,也不是厂商补丁的逐行复现。运行后应输出检查通过。
defnext_step(status,location,redirect_mode):if300<=status<400andlocation:ifredirect_mode=='error':return'REJECT'ifredirect_mode=='manual':return'RETURN_REDIRECT_WITHOUT_REQUEST'return'FOLLOW'return'RETURN_RESPONSE'assertnext_step(302,'https://example.invalid/b','manual')=='RETURN_REDIRECT_WITHOUT_REQUEST'assertnext_step(302,'https://example.invalid/b','error')=='REJECT'assertnext_step(200,None,'manual')=='RETURN_RESPONSE'print('redirect-policy checks passed')模型测试通过只证明这些固定输入满足预期,不能证明生产部署已经修复。实际回归还需要在目标版本、真实适配层或调用封装中重复验证同一不变量。测试用例应同时覆盖正常输入和拒绝路径,否则“全部拒绝”的错误实现也可能被误当成安全修复。
五、研发与安全团队行动清单
P0:升级Axios到1.20.0或确认包含修复的版本;核对实际适配器。按官方临时建议,在支持的运行时显式使用fetchOptions.redirect为manual,或者选择支持相应限制的Node HTTP适配器。
P1:将Node、Bun、Deno或边缘运行时分开建立测试矩阵,不从产品名称推断适配器。用本地桩计数请求次数,确保禁止跳转时后续请求数为零。同步审查手动跳转代码和代理配置。
P2:把安全选项列成适配器能力表,对无法实现的约束在初始化时失败。网络层限制敏感网段访问;日志保留适配器、目的地主机和跳转拒绝原因,避免记录URL中的凭据与令牌。
如何形成可复核的修复证据
研发负责提交调用点、配置差异和回归结果;平台团队负责证明新构建已部署到实际实例;安全团队复核前提是否消除,并保留未覆盖环境的清单。完成条件应落在运行中的版本与行为,而非工单状态或补丁合并时间。
建议对每个服务记录:组件实际版本、受影响功能是否启用、输入来源、修复负责人、部署批次及失败回滚方案。无需搜集完整敏感输入;用脱敏样本和配置摘要通常更适合审计。对于无法及时升级的实例,临时措施必须指定复核日期,避免长期漂移为默认设计。
六、总结
这项问题提醒我们:安全约束必须与最终执行语义一致。识别依赖版本、定位真实调用链、验证负向行为、确认部署完成,缺少任何一步都可能让修复停留在纸面。本文的工程建议用于补充系统设计,不应被误读为厂商已确认的额外攻击链。