curl 8.18.0 修了 6 个 CVE:带 -L 跟丢重定向时,Bearer token 会被一起送到目标
版本发布说明:curl.se/ch/8.18.0.html
作者博客:curl 8.18.0(2026-01-07)
8.18.0 是 curl 的第 272 个版本,距上个版本 63 天,包含 391 个 bugfix 和 6 个安全修复,历史累计安全修复达到 176 个。六个 CVE 里,对日常调 API 的脚本影响最直接的是 CVE-2025-14524。
CVE-2025-14524:跨协议重定向时 bearer token 泄漏
现象
用 curl 带 Authorization: Bearer 调一个 API,服务端返回 302,Location 指向另一个协议或另一个主机。curl 加了 -L / --location 就会跟过去,而原来那份 bearer 凭证也跟着一起进了新请求。新目标可能只是 http、可能是第三方主机,token 就这样被交出去了。
触发条件与 8.18 的修法
触发需要三个条件同时成立:
- 请求里使用了 bearer 凭证(
Authorization: Bearer ...这类); - 服务端返回了重定向;
- 调用方开启了自动跟随(
-L/--location)。
8.18.0 对应的改动是 changelog 里的这条:
curl_sasl: if redirected, require permission to use bearer
即重定向发生后,curl 不再默认沿用 bearer 凭证继续请求,必须拿到显式许可才继续使用。默认行为从"跟着走并带上凭证"改成"不自动带"。
自查
第一步确认版本:
curl --version
首行版本号低于 8.18.0 的都在受影响范围内。
第二步找出脚本里同时出现重定向和凭证的位置:
# 粗筛:同一文件里既有 -L/--location,又有 Authorization
grep -rlE -- '(--location|-L)([ =]|$)' /path/to/scripts \
| xargs grep -lE 'Authorization[[:space:]]*:' 2>/dev/null
--oauth2-bearer 也一并查,凡是把凭证塞进请求头再开自动跟随的写法,都值得人工过一遍。粗筛会有误报(例如 -L 出现在别的参数值里),命中后逐个确认。
缓解顺序
- 升级到 8.18.0 或更高。这是唯一从根上修掉问题的做法,其余都是绕。
- 短期内升不了,限制重定向能去的协议:
curl --proto '=https' --proto-redir '=https' -L ...
初始请求和重定向目标都只允许 https,避免被 302 带到明文 http 或其它协议上。
3. 不要 -L,由调用方自己处理跳转。拿到 3xx 后判断 Location 的目标是否可信,再由自己决定要不要重新发一次请求、要不要带凭证。
4. 让 bearer 凭证只走同源。跳转目标与原始 API 不同源时,一律不带 Authorization。
关闭重定向不是全部答案
--proto-redir '=https' 只约束重定向的协议,不约束主机。同协议、跨主机的跳转仍然会把 header 原样带过去——https 到 https,只要换了 host,凭证照样出境。所以协议限制是降级手段,不是等价修复;真正要控制的是"这份凭证允许发给谁"。
同版本的另外五个 CVE
- CVE-2025-13034:使用 GnuTLS 时,HTTP/3 会跳过 pinning 检查。
- CVE-2025-14017:线程化 LDAPS 场景下 TLS 选项失效。
- CVE-2025-14819:OpenSSL partial chain store 策略被绕过。
- CVE-2025-15079:libssh 全局 knownhost 覆盖。
- CVE-2025-15224:libssh 在未设置 agent 时,密钥口令可被绕过。
这五个不都落在"命令行跑一下"的场景里:LDAPS、libssh、TLS 后端策略,很多是通过 libcurl 被上层程序调用的。
为什么内嵌 libcurl 的组件也要升级
curl --version 只反映命令行工具本身。任何静态或动态链接 libcurl 的程序——SDK、数据同步工具、堡垒机客户端、备份 Agent——用的是它自己那份 libcurl,命令行升级了不代表它们修了。上面 LDAPS 与 libssh 的两条尤其如此:出问题的是库内部的 TLS 与认证路径,只有替换 libcurl 才会生效。核查时要把这些二进制的版本一起看。
批量核查版本与脚本
#!/bin/sh
# 1) 命令行 curl 版本
curl --version | awk 'NR==1{print "cli:", $1, $2}'
# 2) 系统里各份 libcurl 编译进去的版本串
for so in $(find /usr /usr/local /opt -name 'libcurl.so*' 2>/dev/null); do
printf '%s -> ' "$so"
strings "$so" | grep -m1 -E '^libcurl/[0-9]' || echo unknown
done
# 3) 脚本粗筛:重定向 + 凭证同现
grep -rlE -- '(--location|-L)([ =]|$)' /path/to/scripts \
| xargs grep -lE 'Authorization[[:space:]]*:|--oauth2-bearer' 2>/dev/null
第 2 步输出里低于 libcurl/8.18.0 的,按上面的顺序处理;第 3 步命中的文件,确认是"服务端会跳转 + 带 bearer"的组合后,优先改脚本或加 --proto-redir。
其它变更与版本节奏
8.18.0 同时放弃了对 VS2008、Windows CE/CeGCC 的支持;GnuTLS 最低要求提到 3.6.5,并实现了 CURLOPT_CAINFO_BLOB;OpenSSL 最低要求提到 3.0.0。构建环境卡在这些旧依赖上的,升级前先确认。
后续版本计划:8.19.0(2026-03-11)、8.20.0(2026-04-29)、8.21.0(2026-06-24)、8.22.0(2026-09-02,21 个漏洞)、8.23.0(2026-10-14),再下一个计划在 2026-12-09。