恶意 Rust 库 arrayref 在构建时运行负载:编译器也成了攻击入口
据 SafeDep 的分析 报道,Rust crate arrayref 的 0.3.10 版本被发现带入恶意依赖 proc-macro1。真正执行下载和运行负载的不是 arrayref 的宏代码,而是依赖包里的 build.rs。只要项目重新解析依赖并完成编译,恶意代码就可能在程序运行前执行。
据 SafeDep 的分析 报道,Rust crate arrayref 的 0.3.10 版本被发现带入恶意依赖 proc-macro1。真正执行下载和运行负载的不是 arrayref 的宏代码,而是依赖包里的 build.rs。只要项目重新解析依赖并完成编译,恶意代码就可能在程序运行前执行。
这起事件最值得开发者警惕的地方,是它没有依赖一个看起来很可疑的库名。攻击者使用了接近真实 proc-macro2 的拼写,把正常源码复制进 proc-macro1,再把恶意逻辑放在构建脚本里。代码能正常编译,反而让“编译成功”变成了掩护。
根据分析,arrayref 0.3.10 新增了对 proc-macro1 1.0.107 的依赖。后者的构建脚本会拼出远程地址,下载与系统架构对应的二进制文件,并在 Linux、macOS 或 Windows 上启动。它还通过放宽 TLS 证书校验,降低了直接使用 IP 地址下载负载的门槛。
攻击传播利用了 Cargo 依赖解析的一个现实细节:当旧版本被撤回后,开发者可能会被提示升级到唯一尚未被撤回的新版本。如果这个新版本正好携带恶意依赖,版本更新提示就不再只是维护信息,而成了诱导路径。arrayref 又经常作为 GUI 和图形库的传递依赖出现,使用者未必在自己的 Cargo.toml 里直接写过它。
这不是 Rust 特有的“语言不安全”问题。Cargo 会构建声明的依赖,而构建脚本本来就有下载文件、访问环境变量和执行外部命令的能力。Rust 的类型系统可以帮助防止运行时内存错误,却不能替开发者判断一个依赖的维护者身份、版本变更和构建期行为是否可信。

关键事实
- 受影响版本:
arrayref0.3.10,以及被报告为冒名或恶意的proc-macro1版本。 - 攻击时机:构建期,不需要等最终程序启动。
- 传播方式:依赖版本更新、传递依赖和被冒用的维护者身份。
- 处置情况:相关恶意版本已从 crates.io 移除;是否实际执行过负载,仍需结合本地构建日志和网络日志判断。
OC 判断
依赖安全的检查单位不能只停留在“这个库有没有漏洞”。对 Rust、Node.js、Python 等生态而言,真正需要审计的是一次构建会拉下哪些包、运行哪些脚本、连接哪些地址。锁文件只能固定版本,不能自动证明版本没有被接管。
为什么重要
- 对开发者:重新生成锁文件或清理缓存后构建,都可能重新触发依赖解析。
- 对团队:CI 应记录依赖来源、构建脚本行为和出站网络,而不是只保存编译结果。
- 对生态:热门传递依赖的维护者账户和发布权限,已经是基础设施安全的一部分。
评论
围绕这篇文章补充信息、提出问题或分享观察。