Chromium 第三方 Rust crate 安全审计:comprehensive-rust 课程中的审查流程与实操清单

原创2026-09-09 13:37:051,326 阅读
文章标签:文档教程

Chromium 第三方 Rust crate 安全审计:comprehensive-rust 课程中的审查流程与实操清单

本篇指南聚焦 Chromium 中引入第三方 Rust crate 时的安全审计环节:在 gn/ninja 构建体系下,如何对一个(往往带有一串传递依赖的)新 crate 进行系统化审查,包括理解依赖意图、排查 unsafe 代码、扫描已知漏洞与恶意代码,并介绍了 Chromium 向 cargo vet 自动化审计迁移的长期方向。读完本文,你将掌握一份可直接套用的六步审计清单,以及如何与 security@chromium.org 协作建立对第三方 crate 的安全信心。

本文内容来自 comprehensive-rust 课程 Chromium 专题的 "Adding Third Party Crates" 章节,审计部分对应的原始讲义为 reviews-and-audits.md。

一、审计在第三方 crate 引入流程中的位置

在 Chromium 中引入一个 Rust 库并非"加一行依赖"那么简单,而是一条完整的流水线,安全审计是其中承上启下的关键一环:

  1. 下载:用 gnrt(通过 vpython3 tools/crates/run_gnrt.py -- vendor)把目标 crate 及其直接/传递依赖一并 vendor 进 //third_party/rust/chromium_crates_io,参见 downloading-crates.md;
  2. 配置:在中央 Cargo.toml 中声明依赖与 features,并在 gnrt_config.toml 中声明 group 与许可证位置,参见 configuring-gnrt-config-toml.md;
  3. 生成构建规则:解决 build.rs 与 gn 静态构建规则的冲突,参见 resolving-problems.md;
  4. 安全审计(本文主题):对进入代码库的每一份代码进行安全审查;
  5. 入库:连同 BUILD.gn、README.chromium、OWNERS 一起落地,参见 checking-in.md;
  6. 持续维护:作为依赖 OWNER 持续跟进安全更新,参见 keeping-up-to-date.md。

新增库首先要遵守 Chromium 标准的第三方依赖政策,但仅仅"合规"远远不够——你还必须对引入的代码本身负责。由于 Rust 生态中"为了一点功能就互相依赖"非常普遍,你带进来的往往不是单个 crate,而是一整棵传递依赖树,这意味着有相当规模的代码需要逐行审查。

二、为什么 crate 审计与 C++ 库审计如此不同

要理解审计策略,先要看清 Rust crate 与 C++ 库在生态形态上的根本差异。adding-third-party-crates.md 给出了一张直观对比表:

属性 C++ 库 Rust crate
构建系统 多种多样 高度统一:Cargo.toml
典型库规模 偏大 偏小
传递依赖 很少 很多

这张表在 Chromium 工程师视角下意味着:

  • 利:所有 crate 共用一套构建系统(Cargo.toml),因此可以自动化地把它们纳入 Chromium 的构建体系;
  • 弊:crate 之间极易互相依赖,你通常得一次性引入多个库,审查面随之扩大。

与此同时,安全 Rust 代码能造成的负面影响是有限的——借用检查与所有权模型在编译期就消除了大量内存安全类漏洞。因此审计的注意力应当重点集中在 unsafe 代码、build.rs/过程宏等"脱轨"地带,而不是对所有安全代码一视同仁地逐行精读。这构成了 Chromium crate 审计策略的总纲:区分风险、聚焦要害。

三、六步审计清单:逐条展开的实操指南

原讲义明确指出,现阶段 Chromium 对每个新引入的 crate 都会执行以下检查。以下逐条展开其意图与操作要点。

第 1 步:理解每个 crate 的用途与依赖关系

先回答两个问题:为什么需要这个 crate?它和别的 crate 是什么关系? 这是整个审计的基础——如果你连引入动机都说服不了自己,后面的深度审查就没有意义。

接下来重点检查 crate 构建过程中"会执行任意代码"的部分:

  • build.rs:Cargo 允许 crate 附带构建脚本,它在编译期执行任意操作。这与 gn/ninja 追求"静态、确定性构建规则以最大化并行度与可重复性"的设计哲学存在根本冲突。针对 build.rs 的不同效果,resolving-problems.md 给出了兼容性对照表:
build script 效果 我们的 gn 模板是否支持 你需要做的工作
检查 rustc 版本以开关 feature 支持 无
检查平台/CPU 以开关 feature 支持 无
生成代码 支持 有——在 gnrt_config.toml 中指定
构建 C/C++ 不支持 打补丁绕过
其他任意操作 不支持 打补丁绕过

值得庆幸的是,大多数 crate 并不包含构建脚本,而包含构建脚本的 crate 里,绝大多数也只做了表中前两类"人畜无害"的检查。审计时只需确认你引入的 crate 的 build.rs 行为落在受支持区间内即可。

  • 过程宏(procedural macros):同样在编译期执行代码,属于"在编译时运行的任意程序",需要和 build.rs 一视同仁地弄清其用途。

  • 兼容性判断:把上述发现对照"Chromium 的常规构建方式"(静态、确定性、可并行)逐条验证,确认这些编译期行为不会破坏 Chromium 的构建模型。

第 2 步:检查 crate 是否维护良好

一个无人维护、长期不发布、不响应安全通告的 crate,即使当下代码无漏洞,也会成为未来的供应链风险。审计时关注:

  • 上游是否仍在活跃维护、是否定期发版;
  • 已知问题与安全公告是否有回应;
  • 结合第 6 步的持续更新义务(见后文"审计之后的持续责任"),判断自己是否愿意长期为它背书。

第 3 步:用 cargo audit 扫描已知漏洞

Chromium 的 crate 全部 vendor 在 //third_party/rust/chromium_crates_io,在该目录下执行:

cd third-party/rust/chromium_crates_io
cargo audit

cargo audit 会对照 RustSec 漏洞数据库检查依赖树中已知的、存在 CVE 的 crate 版本,是审计中性价比最高的一道自动关卡。

使用前提是先安装该工具:

cargo install cargo-audit

讲义特意点出了一个略带讽刺意味的事实:cargo install 本身就意味着从互联网下载大量依赖才能把审计工具装起来。这与课程在 cargo.md 中讨论的信任模型一脉相承——你需要审慎权衡"审计工具自身的供应链"与"被你审计的 crate 的供应链"这两组信任边界。

第 4 步:确保 unsafe 代码满足 Rule of Two

安全 Rust 的负面副作用有限,但 unsafe 代码一旦出错,后果与 C/C++ 无异。Chromium 对此的硬性门槛是 Rule of Two:任何涉及内存安全的代码,至多只能同时面对两个危险输入中的一个——要么是不可信输入,要么是脆弱的处理过程(如高度复杂、难以验证的解析逻辑)。两条同时满足即不合格。

审计时逐处检查 crate 中的 unsafe 块/函数,确认其安全前提清晰、注释完整、调用路径可验证。

与配置文件的联动:这一要求直接映射到 gnrt_config.toml 中的 group 字段。configuring-gnrt-config-toml.md 定义了三种分组:

#   'safe': The library satisfies the rule-of-2 and can be used in any process.
#   'sandbox': The library does not satisfy the rule-of-2 and must be used in
#              a sandboxed process such as the renderer or a utility process.
#   'test': The library is only used in tests.

例如:

[crate.my-new-crate]
group = 'test' # only used in test code

也就是说:Rule of Two 审查结论是决定 crate 能在哪种进程里使用的依据。不满足 Rule of Two 的库并非不可用,而是必须被限制在沙箱化进程(如 renderer 或 utility 进程)中,以降低攻击面。审计者在第 4 步的结论,应当与第 1 步配置阶段填写的 group 一致并相互印证。

第 5 步:检查 fs 与 net API 的使用

即使代码本身内存安全,一个会读写文件系统、发起网络请求的库也可能引入 Chromium 无法接受的行为:

  • 文件系统(fs):可能读取/写入敏感路径,或在构建期、运行期产生非预期的副作用;
  • 网络(net):可能导致数据外泄、引入远程代码交互,或破坏 Chromium 的隐私与安全边界。

对这两类 API 的每一处使用,都要弄清"为什么在这里访问文件/网络""数据流向哪里"。任何说不清用途的 fs/net 调用,都是需要重点怀疑的对象。

第 6 步:通读全部代码,排查恶意插入

这是最"硬核"的一步:以足够深的程度阅读全部代码,查找任何可疑的、可能被恶意植入的内容。为什么需要这样做?因为第三方 crate 可能在上游被投毒(例如维护者账号失陷、恶意 PR 混入),而供应链攻击往往就藏在不起眼的角落——一个看似合理的算法、一段"多余"的常量表、一次隐蔽的字符替换。

讲义同时给出了务实的边界:不必也不应以 100% 完美为目标——代码量往往太大,现实中无法做到绝对穷尽。合理的策略是:

  • 对高风险的 unsafe、build.rs、过程宏、fs/net 相关代码重点精读;
  • 对安全 Rust 代码做代表性抽查;
  • 把"无法完全排除风险"作为已知事实接受,并靠第 4 步的进程隔离与第 3 步的自动扫描兜底。

四、迈向 cargo vet:自动化审计的未来方向

人工逐 crate 审查(尤其是第 6 步)成本高昂且难以复用。讲义明确指出:随着时间推移,Chromium 的目标是转向以 cargo vet 为基础的审计流程。

cargo vet 是 Mozilla 主导的供应链审计工具,核心理念是"审计结论可以共享与复用":你审计过的 crate 及其结论会形成一份可提交的审计记录(audit 文件),其他团队可以据此快速建立信任,而不必从零开始逐行重读。cargo.md 在讨论 Cargo 生态时也提到,cargo vet 正是"streamlining and sharing security audits(简化并共享安全审计)"的代表性工具,与 cargo audit(查已知漏洞)形成互补:cargo audit 回答"这个版本有没有已知漏洞",cargo vet 回答"这段代码有没有被人审过、审得怎么样"。

需要说明的是,这属于长期演进方向;在 cargo vet 流程全面落地之前,本节给出的六步人工清单仍是实际执行的标准。

五、与 security@chromium.org 协作:清单之外的正确姿势

讲义特别强调:以上六条只是指导方针(guidelines),不是教条。每个 crate 的情况不同,"怎么审查才能对它有信心"的最终裁定权,在与 security@chromium.org 的审查者们共同协商的过程中。

实践中这意味着:

  • 引入新 crate 时,主动把审计发现(build.rs 行为、unsafe 分布、fs/net 使用点、group 归类建议)整理给安全审查者;
  • 对拿不准的高风险点(例如复杂的 unsafe 代码、可疑的网络行为),宁可多问一次也不要自行放行;
  • 让审查深度与被审 crate 的风险等级匹配,避免"一刀切"的过度或不足。

六、审计之后的持续责任

审计不是一次性动作。作为第三方依赖的 OWNER,你有义务持续跟进安全修复并升级依赖(参见 keeping-up-to-date.md)。这意味着:

  • 每次升级 crate 版本,都要重新走一遍审计流程——尤其关注新版本中新增的 unsafe 代码、build.rs 变更和依赖树变化;
  • 上游发布安全修复后,及时把修复合入(Chromium 的 //third_party/rust/chromium_crates_io/patches 机制可以承载对特定 crate 的补丁,见 downloading-crates.md);
  • 直到审计流程自动化(cargo vet 落地)之前,这份人工责任都落在每个引入者身上——正如对其他任何第三方依赖一样。

小结:一份可复用的审计检查单

把全文压缩成一张可执行的检查单,供你在引入任何新 crate 时逐项打勾:

  1. 意图:这个 crate 为什么被引入?与已有 crate 是什么关系?
  2. 编译期行为:build.rs/过程宏在做什么?是否与 gn/ninja 静态构建兼容?
  3. 维护状态:上游是否活跃、安全通告是否及时响应?
  4. 已知漏洞:cd third-party/rust/chromium_crates_io && cargo audit 结果是否干净?
  5. unsafe 与 Rule of Two:每处 unsafe 是否满足"不可信输入、脆弱处理过程二选一"?gnrt_config.toml 的 group 归类是否与之匹配?
  6. fs/net:所有文件系统与网络调用是否都有正当理由?
  7. 通读排查:是否以足够深度通读代码,确认没有恶意植入?
  8. 与安全团队对齐:结论是否与 security@chromium.org 达成一致?
  9. 长期责任:是否确认自己作为 OWNER 会持续跟进安全更新与再审计?

在 Chromium 这样对安全性有极致要求的代码库中,引入 Rust crate 从来不只是"改一行 Cargo.toml"——一套严格但务实的审计流程,才是让供应链既高效又可信的保障。

登录后查看全文
comprehensive-rust