你以为换个 cargo 源只是配置问题?今天 Cargo 的 URL 标准化 bug 把三千多个仓库的 token 彻底漏了
Cargo 的 1.68 到 1.95 有一个 URL 标准化逻辑 bug:对稀疏索引(sparse index)源,它错误地剥离了 .git 后缀。攻击者如果同时满足两个条件——在同一个域名下既发布了一个 crate,又托管了一个带 .git 后缀的路径——就能截获受害者的认证令牌。
Rust 官方在 1.96.0 里修了它。但因为 Rust 更新频率,这个 bug 悄悄在三千多个发布版本里存活了快两年。
漏洞是怎么工作的
Cargo 在发布和安装依赖时,需要从注册表(Registry)拉取索引。稀疏索引协议(sparse index)是 2022 年引入的,让 Cargo 直接通过 https://Index.Crates.io 这类地址查询包信息,而不需要克隆整个 git 仓库。
问题出在 URL 标准化这一步。Cargo 会在发出请求前,对目标 URL 做规范化处理——比如把 https://my-registry.example.com/api/v1/crates/foo 和 https://my-registry.example.com/api/v1/crates/foo.git 当作同一个地址处理。
攻击者的攻击路径是这样的:
-
注册一个与目标公司同域名的包
比如目标公司内部 registry 是https://crates.mycompany.com,攻击者注册一个crates.mycompany.com/foo的公开包。 -
在同一域名下托管一个带
.git的路径
攻击者在自己的服务器上放置一个https://crates.mycompany.com/some-package.git/路径。 -
利用 Cargo 的错误标准化
当受害者安装了攻击者发布的包,Cargo 在处理某些请求时,会把本该发往官方 registry 的认证令牌,通过这个.git路径泄露给攻击者服务器。
本质上,这是路径混淆——Cargo 把「发给我自己 registry 的令牌」错误地发到了攻击者控制的地址。
两个 CVE,一个比一个有意思
Rust 1.96.0 修了两个安全漏洞:
CVE-2026-5222(低危)
就是这个 URL 标准化 bug。修复方式是:.git 后缀剥离现在只对 git-protocol 类型的注册表生效,稀疏索引不受影响。
CVE-2026-5223(中危)
tarball 符号链接提取问题。Cargo 在解压依赖的 tar.gz 时,如果没有正确验证符号链接的目标路径,攻击者可以构造一个指向仓库外的文件路径,让 Cargo 在提取时覆盖系统文件或读取敏感文件。
你的 Cargo 在哪个版本?
最简单的方式:
cargo --version
# Cargo 1.95.0(受影响)
# Cargo 1.96.0(已修复)
或者直接用 rustup 更新到最新稳定版:
rustup update stable
如果是 1.68 到 1.95 之间的任何版本,都需要更新。这涵盖了从 2023年4月 到 2026年9月 的所有 Rust 版本——基本上如果你没有定期更新工具链,很可能中招。
如果你用的是 crates.io 官方源
好消息是,这个漏洞不直接影响 crates.io 用户。官方的索引托管在 GitHub Pages 上,不存在攻击者控制同域名路径的情况。
但如果你用的是私有 registry(比如公司内部的 Cargo 源),风险就真实存在了。特别是如果你允许从非官方源发布包,或者 registry 和其他服务共享域名。
三步检查清单
-
查版本
cargo --version如果是
1.95.0或以下,立刻rustup update stable。 -
查私有源配置
cat ~/.cargo/config.toml确认你用的 registry 地址是否与公司其他服务共享域名。
-
查 CI 日志
如果你的 CI 在每次构建时自动调用cargo install或cargo update,确认 CI 环境里的 Rust 版本是最新的。很多 CI 镜像会预装旧版本 Rust 但不自动更新。
这个 bug 的狡猾之处在于:它不要求攻击者黑进你的系统,只需要在同一个域名下注册一个公开包。你可能永远不知道自己的 token 什么时候漏了——Cargo 不会报错,请求看起来完全正常。
定期更新 Rust 工具链,不只是为了性能和新特性,也是最简单、最便宜的安全防线。
评论区
登录后可评论。