☰
SurrealDB 供应链安全实践:基于 cargo-vet 与 cargo-deny 的 Rust 依赖审查机制
2026/10/9 8:41:01 网站建设 项目流程

SurrealDB 供应链安全实践:基于 cargo-vet 与 cargo-deny 的 Rust 依赖审查机制

【免费下载链接】surrealdbA scalable, distributed, collaborative, document-graph database, for the realtime web项目地址: https://gitcode.com/GitHub_Trending/su/surrealdb

导读

供应链攻击已成为开源软件面临的主要安全威胁之一——攻击者不再直接攻击项目自身代码,而是通过向第三方依赖中注入恶意代码来间接渗透。本文以 SurrealDB 仓库(一个可扩展、分布式、面向实时 Web 的文档图数据库)的 supply-chain/README.md 为核心骨架,系统讲解该仓库如何通过cargo-vet与cargo-deny建立依赖审查机制、如何在 CI 中落地执行、贡献者遇到依赖检查失败时的完整处理流程,以及工作区内 crates.io 发布包的信任策略。读完本文,你将掌握一套可复制的 Rust 依赖供应链安全基线方案,并能直接对照仓库中的 deny.toml、supply-chain/config.toml、supply-chain/audits.toml 与 supply-chain/imports.lock 理解每一处配置背后的安全意图。

一、供应链安全目标:压缩攻击面,抬高攻击门槛

SurrealDB 将供应链安全的核心目标定义为:减轻攻击者向 SurrealDB 所依赖的第三方依赖中注入恶意代码所造成的影响。在当前阶段,其具体目标有三层:

  1. 在 CI 流程中考虑依赖的来源与访问权限——建立一套基础机制,让"依赖是否可信"成为持续集成过程的一部分;
  2. 限制完全暴露于供应链攻击的依赖数量——缩小 SurrealDB 的依赖攻击面;
  3. 抬高针对现有依赖发起成功供应链攻击所需的成本——即便攻击者想动手,也面临更高门槛。

这与仓库根目录 SECURITY.md 中声明的整体安全策略相互呼应:后者负责"已知漏洞"(known vulnerabilities)的检查(cargo deny check、Dependabot alerts、OSS-Fuzz 模糊测试),而本文所讲的供应链机制则着眼于"未知的恶意代码注入"风险。两者共同构成 SurrealDB 依赖安全的两道防线。

二、核心机制:cargo-vet 基础配置 + CI 强制执行

当前阶段,SurrealDB 的供应链安全实现为对主仓库进行的一版基础cargo-vet配置,该工具作为 CI 的一部分执行。相关配置文件的所有权归属为@surrealdb/security团队,这一点在 .github/CODEOWNERS 中有明确登记——不仅是supply-chain/*目录,包括Cargo.lock、Cargo.toml、deny.toml、SECURITY.md甚至CLAUDE.md等安全敏感文件都由该团队负责审阅。

2.1 为什么需要 cargo-vet

Rust 生态的依赖数量庞大(SurrealDB 的Cargo.lock中锁定了数以千计的传递依赖),项目自身无法对每个依赖进行深度人工审计。cargo-vet的设计思路是"审计复用":将"哪些 crate 被谁、以什么标准审计过"以结构化数据形式沉淀下来,并支持从其他可信组织导入审计结论,从而让项目以较小的成本获得较广的覆盖。SurrealDB 的仓库目录中恰好保存了该工具的三个关键状态文件:

文件作用
supply-chain/config.tomlcargo-vet主配置:版本、外部审计源导入、工作区 crate 信任策略、豁免清单
supply-chain/audits.toml项目自身的审计与信任记录([[audits.*]]、[[trusted.*]])
supply-chain/imports.lock从外部导入审计数据的锁定记录,以及 crates.io 上 crate 发布者身份([[publisher.*]])的哈希锁定

2.2 外部审计源:信任的传导网络

config.toml 通过[imports.*]段落从 7 个可信组织导入审计结论,实现"一次审计、多方受益":

[imports.bytecode-alliance] url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml" [imports.embark-studios] url = "https://raw.githubusercontent.com/EmbarkStudios/rust-ecosystem/main/audits.toml" [imports.fermyon] url = "https://raw.githubusercontent.com/fermyon/spin/main/supply-chain/audits.toml" [imports.google] url = "https://raw.githubusercontent.com/google/supply-chain/main/audits.toml" [imports.isrg] url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml" [imports.mozilla] url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml" [imports.zcash] url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml"

这些组织(字节码联盟、Embark Studios、Fermyon、Google、ISRG、Mozilla、Zcash 生态)均长期维护自己的cargo-vet审计数据。配合 imports.lock 中记录的发布者身份信息,cargo-vet得以判断:一个依赖要么由可信发布者发布、要么已被某个可信组织直接审计过。

2.3 明确承认的当前妥协

文档坦率地承认,由于缺少专职资源对依赖进行深度审计,当前实现做了三方面妥协:

  • SurrealDB 员工发布的依赖默认受信任——条件是这些员工是唯一发布者;
  • 被某些可信组织直接(非传递性)审计过的依赖默认受信任;
  • 任何尚未被审计的依赖都豁免于审查流程。

同时文档特别强调:在本实现中,cargo-vet仅作为信息收集工具使用,SurrealDB 并不会对第三方依赖进行实质性的安全审查。工具的实际职责是:收集第三方审计信息,以及盘点哪些依赖由可信开发者发布。换句话说,这一机制的定位是"降低攻击面、提高攻击成本"的防御纵深,而非替代人工安全审计的最终保障。

三、本地工具安装与依赖检查失败的处理流程

3.1 安装依赖检查工具

贡献者如需在本地复现 CI 的依赖检查,需要安装两个工具:

cargo install --locked cargo-deny cargo install --locked cargo-vet

--locked参数确保安装的版本与Cargo.lock中锁定的版本一致,避免工具本身被悄悄升级引入意外行为。

3.2 分支一:cargo-deny 检查失败(已知漏洞)

cargo-deny的职责是扫描已知安全漏洞(RUSTSEC 公告)、许可证合规、依赖来源与重复版本等。当依赖检查 action 因cargo-deny失败时,按以下流程处理:

  1. 定位受影响的依赖;
  2. 在单独分支上运行cargo update <PACKAGE>尝试升级;
  3. 如果没有修复版本或无法升级:
    • 在 deny.toml 的[advisories]段中添加例外条目;
    • 在例外条目上附加注释,说明豁免理由及移除条件;
  4. 通过独立 PR 提交变更,并在 PR 中粘贴cargo-deny提供的漏洞详情;
  5. 该依赖更新 PR 由@surrealdb/security批准;
  6. Rebase 你的原始分支,使依赖升级生效。

关于第 3 步,仓库 deny.toml 的[advisories]段正是这一机制的落地样本——文件顶部用多行注释详细记录了每个被忽略公告的来龙去脉,例如:

# TODOs: # - for RUSTSEC-2025-0134, rustls-pemfile is unmaintained (archived) but pulled in transitively # by tonic and axum-server. Upstream crates need to migrate to rustls-pki-types. # - for RUSTSEC-2025-0141, bincode is unmaintained but considered complete and stable at v1.3.3. # Plan migration to wincode, postcard, bitcode, or rkyv in future. Also need surrealmx to update. # - for RUSTSEC-2023-0071, rsa gas a constant-time implementation allowing attackers to recover keys # - for RUSTSEC-2024-0436, paste is now unmaintained and archived, but we only use paste in tests # - for RUSTSEC-2026-0097, rand ThreadRng unsoundness under a narrow combination ... # - for RUSTSEC-2026-0098 and RUSTSEC-2026-0099, rustls-webpki 0.101.7 has name-constraint # handling bugs ... ignore = ["RUSTSEC-2025-0134", "RUSTSEC-2025-0141", "RUSTSEC-2023-0071", "RUSTSEC-2024-0436", "RUSTSEC-2026-0097", "RUSTSEC-2026-0098", "RUSTSEC-2026-0099"]

这是一份极佳的"例外管理"范本:每个被忽略的公告都附有上游迁移计划或使用场景限制(如"仅在测试中使用""等待上游 crate 升级 tonic"),使得例外不是永久免责,而是可追踪、有条件、带退出路径的临时处置。此外 deny.toml 还配置了依赖来源白名单([sources]段仅允许 crates.io 索引)、许可证白名单([licenses]段允许 MIT、Apache-2.0、BSD、MPL-2.0 等 14 类许可),并对 SurrealDB 自家 crate(如surrealdb、surrealdb-core、surrealdb-server、surrealism-runtime、surrealml-core等)通过[[licenses.exceptions]]单独放行 BUSL-1.1 / Apache-2.0 许可。

3.3 分支二:cargo-vet 检查失败(依赖未经信任/审计/豁免)

当 action 因cargo-vet失败时,含义是:该依赖尚未被信任(trusted)、未被审计(audited),也未获得豁免(exempted)。处理流程如下:

  1. 若是新依赖,先思考它是否真的有必要引入 SurrealDB;
  2. 若确定要引入,分两种情况:
    • 依赖由 SurrealDB 员工发布(且所有发布者都是 SurrealDB 员工):可标记为safe-to-deploy信任:
      cargo vet trust <PACKAGE>
    • 其他情况:现阶段可将其豁免于审查流程:
      cargo vet add-exemption <PACKAGE>
  3. 清理审计列表,移除过时条目:
    cargo vet prune
  4. 变更由@surrealdb/security批准。

从 supply-chain/audits.toml 的条目格式可以看出这一流程沉淀后的实际形态:

# 由项目成员亲自审计的 crate(可精确到具体版本或版本增量区间) [[audits.easy-parallel]] who = "Emmanuel Keller <emmanuel.keller@surrealdb.com>" criteria = "safe-to-deploy" version = "3.3.1" notes = "A very simple one file library, no unsafe code." [[audits.quick-xml]] who = "Micha de Vries <micha@devrie.sh>" criteria = "safe-to-deploy" delta = "0.26.0 -> 0.37.2" # 按发布者身份信任的 crate(带发布者 user-id 与信任时间区间) [[trusted.aho-corasick]] criteria = "safe-to-deploy" user-id = 189 # Andrew Gallant (BurntSushi) start = "2019-02-25" end = "2026-11-06"

值得注意的细节:

  • versionvsdelta:version = "x.y.z"表示对特定版本做了完整审计;delta = "a.b.c -> d.e.f"表示基于上一版本的审计结论、仅审查了增量变化,是"升级审计"的高效形式;
  • criteria:常见值为safe-to-deploy(可发布到生产)与safe-to-run(仅可本地运行),后者用于deadpool、globset、asn1-rs等 crate,可见 SurrealDB 对"部署级"与"运行级"信任做了明确区分;
  • notes:审计者可用简短注释说明审计依据(如easy-parallel的"单文件库、无 unsafe 代码");
  • [[trusted.*]]:不针对具体版本,而是基于 crates.io 发布者身份的长期信任,例如 BurntSushi(aho-corasick、regex系列)、dtolnay(anyhow、serde相关)、epage(clap系列)等知名 Rust 生态维护者。

四、工作区 crate 的 crates.io 发布策略

文档明确指出:本仓库的所有工作区 crate(如surrealdb、surrealdb-core、surrealdb-server、surrealism、surrealml-core等)中,部分同时发布到 crates.io。仓库根 Cargo.toml 的工作区成员列表证实了这一点:除了根包外,还包含surrealdb/common、surrealdb/ast、surrealdb/parser、surrealdb/core、surrealdb/server、surrealdb/types、surrealism系列与surrealml/core等多个 crate。

对于这些自有 crate,SurrealDB 在 config.toml 中统一设置了:

[policy.demo] audit-as-crates-io = false [policy.surreal] audit-as-crates-io = false [policy.surrealdb] audit-as-crates-io = false [policy.surrealdb-core] audit-as-crates-io = false [policy.surrealdb-profiling] audit-as-crates-io = false [policy.surrealdb-server] audit-as-crates-io = false [policy.surrealdb-types] audit-as-crates-io = false [policy.surrealdb-types-derive] audit-as-crates-io = false [policy.surrealism] audit-as-crates-io = false [policy.surrealism-macros] audit-as-crates-io = false [policy.surrealism-runtime] audit-as-crates-io = false [policy.surrealism-types] audit-as-crates-io = false [policy.surrealml-core] audit-as-crates-io = false

audit-as-crates-io = false的含义:默认情况下,cargo-vet会把依赖视为从 crates.io 拉取的第三方包并要求审计;而这里显式关闭该行为,使这些 crate 无论版本如何,都被视为可信的第一方代码。这样做的收益是:

  • 避免在升级自有 crate 版本时维护逐版本的豁免或审计记录;
  • 同一份工作区代码既服务于仓库内开发,也服务于 crates.io 发布场景,无需两套信任体系;
  • 下游消费者若使用了这些发布到 crates.io 的 crate,需要在自己的cargo-vet配置中独立处理信任关系——仓库并不替下游消费者做决定。

五、整套机制的落地拼图

将本文涉及的文件串起来,可以得到 SurrealDB 依赖供应链安全的完整拼图:

  1. deny.toml——cargo-deny配置:扫描已知漏洞(RUSTSEC 公告库,数据库路径~/.cargo/advisory-db)、限制依赖来源仅为 crates.io、白名单化许可证、并携带一份带理由与退出条件的公告豁免清单;
  2. supply-chain/config.toml——cargo-vet配置:声明工具版本(version = "0.10")、导入 7 个外部可信组织的审计数据、为全部自有工作区 crate 设置audit-as-crates-io = false,并存放未被信任/审计 crate 的豁免条目([[exemptions.*]],每条附criteria,多数为safe-to-deploy,部分为safe-to-run);
  3. supply-chain/audits.toml——审计状态的核心状态机:[[audits.*]](成员亲自审计的版本/增量)、[[trusted.*]](基于发布者身份的长效信任)、[[certified.*]](按需声明的认证结论)三类记录共存;
  4. supply-chain/imports.lock——外部导入数据的锁定快照与 crates.io 发布者身份指纹(含user-id、user-login、user-name、发布时间),保证信任判断可复现、可审计;
  5. .github/CODEOWNERS——将supply-chain/*、deny.toml、Cargo.lock、Cargo.toml、SECURITY.md等全部安全敏感文件划归@surrealdb/security团队把关,配合 PR 审批流程形成人工复核闭环。

六、结论与适用边界

SurrealDB 的这套供应链安全实现,本质上是在"资源有限"与"风险现实"之间做出的务实平衡:用cargo-vet复用具名组织与可信发布者的审计成果,用cargo-deny挡住已知漏洞与不合规许可证,用audit-as-crates-io = false免去第一方 crate 的重复审查,再用 CODEOWNERS 与双 PR 流程引入人工把关。它不声称提供深度人工审计,而是以"信息收集 + 攻击面收缩 + 门槛抬高"的方式,为大规模 Rust 项目提供了一条低成本、可演进的依赖安全基线。

对于想在自己项目中复用的读者,建议按以下顺序落地:先引入cargo-deny建立漏洞与许可证红线,再配置cargo-vet导入外部审计源并对自有 crate 设置audit-as-crates-io = false,最后将deny.toml、supply-chain/目录与Cargo.lock纳入安全团队的 CODEOWNERS 范围——完整配置均可直接对照本仓库的上述文件逐项参考。

【免费下载链接】surrealdbA scalable, distributed, collaborative, document-graph database, for the realtime web项目地址: https://gitcode.com/GitHub_Trending/su/surrealdb

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询