rust-secure-code/cargo-auditable
GitHub: rust-secure-code/cargo-auditable
将 Rust 项目的完整依赖树嵌入编译后的二进制文件,使生产环境中的可执行文件可在脱离源码的情况下进行漏洞审计和 SBOM 追踪。
Stars: 802 | Forks: 37
## cargo-auditable
了解用于构建 Rust 可执行文件的确切 crate 版本。在生产环境中大规模审计二进制文件的已知错误或安全漏洞,零账簿开销。
其工作原理是将 JSON 格式的依赖树数据嵌入到编译后可执行文件的专用 linker section 中。
官方支持 Linux、Windows 和 Mac OS。从 v0.6.3 版本起也支持 [WebAssembly](https://en.wikipedia.org/wiki/WebAssembly)。所有其他 ELF 目标应该也能工作,但未在 CI 中测试。
最终目标是让 Cargo 自身将此信息编码到二进制文件中。目前有一个关于在 Cargo 内部实现的 RFC,本项目为其铺平了道路:https://github.com/rust-lang/rfcs/pull/2801
## 使用方法
```
# 安装工具
cargo install cargo-auditable cargo-audit
# 构建在二进制文件中嵌入依赖列表的项目
cargo auditable build --release
# 扫描二进制文件以查找漏洞
cargo audit bin target/release/your-project
```
`cargo auditable` 适用于任何 Cargo 命令。所有参数均按原样传递给 `cargo`。
### 在 nightly Rust 上
在 nightly 版本上,我们可以利用 Cargo 的[原生 SBOM 前身](https://doc.rust-lang.org/cargo/reference/unstable.html#sbom) 来更准确地记录依赖项:
```
CARGO_BUILD_SBOM=true cargo +nightly auditable build -Z sbom --release
```
由于 [Cargo 中的一个 bug](https://github.com/rust-lang/cargo/issues/15695),如果您在同一个项目中也曾使用过不带 `-Z sbom` 的 `cargo auditable`,您可能需要先执行 `touch src/*` 或 `cargo clean`。
### 通过其他工具
如果您没有直接调用 `cargo` 且无法更改其调用方式,可以将 `cargo auditable` 用作 `cargo` 的直接替代品。详见[此处](REPLACING_CARGO.md)。
### 用于 Github 发布
[`cargo dist`](https://github.com/axodotdev/cargo-dist) 提供了对 `cargo auditable` 的可选支持,详见[此处](https://axodotdev.github.io/cargo-dist/book/supplychain-security/index.html)。
## 采用情况
Microsoft 内部使用 `cargo auditable`,并曾维护[Go 的数据提取库](https://github.com/microsoft/go-rustaudit)。
多个 Linux 发行版使用 `cargo auditable` 构建其 Rust 软件包:[Alpine Linux](https://www.alpinelinux.org/)、[NixOS](https://nixos.org/)、[openSUSE](https://www.opensuse.org/)、[Void Linux](https://voidlinux.org/)、[Chimera Linux](https://chimera-linux.org/) 和 [Wolfi OS](https://wolfi.dev)。如果您从它们的仓库安装软件包,您可以对其进行审计!
[Chainguard](https://chainguard.dev/) 在其 [rust 基础容器](https://images.chainguard.dev/directory/image/rust/overview) 中包含了 `cargo auditable`,并提供了默认的 `cargo` 包装器以始终调用 `cargo auditable`,因此使用此容器构建的 Rust 应用程序默认是可审计的。
## 常见问题
### 这会使我的二进制文件膨胀吗?
简而言之,不会。即使对于拥有 400 多个条目的大型依赖树,嵌入的依赖列表占用也不到 4kB。这通常仅占二进制文件大小的 1/1000 到 1/10,000。
### 我可以让 `cargo` 总是使用 `cargo auditable` 进行构建吗?
可以!例如,在 Linux/macOS 等系统上,将以下内容添加到您的 `.bashrc` 中:
```
alias cargo="cargo auditable"
```
如果您使用的 shell 不是 bash,或者使用别名不可行,请[参阅此处](REPLACING_CARGO.md)。
### 有没有什么工具可以使用这些数据?
#### 漏洞报告
* [cargo audit](https://crates.io/crates/cargo-audit) v0.17.3+ 可以检测二进制文件中的此数据并报告漏洞。详情请参阅[此处](https://github.com/rustsec/rustsec/tree/main/cargo-audit#cargo-audit-bin-subcommand)。
* [trivy](https://github.com/aquasecurity/trivy) v0.31.0+ 可检测二进制文件中的此数据并报告漏洞。端到端示例请参阅 [v0.31.0 发布说明](https://github.com/aquasecurity/trivy/discussions/2716)。
* [grype](https://github.com/anchore/grype) v0.83.0+ 可检测二进制文件和容器镜像中的此数据并报告漏洞。
* [osv-scanner](https://github.com/google/osv-scanner/) v2.0.1+ 在扫描容器镜像时会[读取此数据](https://github.com/google/osv-scalibr/pull/377)。
#### 恢复依赖列表
* [syft](https://github.com/anchore/syft) v1.15.0+ 支持恢复此数据并将其转换为各种格式。旧版本需要 `--catalogers all` CLI 选项。
* [docker](https://docs.docker.com/build/metadata/attestations/sbom/) 支持将 CycloneDX 文档嵌入到容器镜像中。如果您使用 `docker buildx build --tag /: --attest type=sbom --push .` 构建容器镜像,并在 `Dockerfile` 中使用 `cargo auditable` 构建 rust 二进制文件,那么附加到容器镜像的 SBOM 证明将包含您的 rust 依赖项。此功能由 [BuildKit Syft scanner](https://github.com/docker/buildkit-syft-scanner) 提供支持。
* [blint](https://github.com/owasp-dep-scan/blint) v2.1.3+ 可以恢复此数据并将其输出为 CycloneDX。
* [wasm-tools](https://github.com/bytecodealliance/wasm-tools) v1.227.0+ 可以从 WebAssembly 中恢复此数据。请尝试 `wasm-tools metadata show`。
* [rust-audit-info](https://crates.io/crates/rust-audit-info) 从二进制文件中恢复依赖列表并以 JSON 格式打印。
* [auditable2cdx](https://crates.io/crates/auditable2cdx) 从二进制文件中恢复依赖列表并以 CycloneDX 格式打印。
### 我可以使用不同语言编写的工具读取此数据吗?
可以。该数据格式专为与其他实现的互操作性而设计。事实上,解析它只需要 [5 行 Python 代码](PARSING.md)。有关解析数据的文档,请参阅[此处](PARSING.md)。
此外,Syft 可以读取并将其转换为多种格式。`auditable2cdx` 可以将其转换为 CycloneDX,大多数工具都能理解该格式。这种转换使您甚至可以将此数据提供给无法修改的工具。
### 数据格式具体是什么?
数据格式由 [此处](cargo-auditable.schema.json) 的 JSON schema 描述。
JSON 经过 Zlib 压缩,并放置在名为 `.dep-v0` 的 linker section 中。
您可以在[此处](PARSING.md) 找到有关解析它的更多信息。
### 嵌入式平台怎么办?
对于连一个字节都腾不出来的嵌入式平台,不应在可执行文件中添加任何内容。相反,它们应该将每个可执行文件的哈希值记录在数据库中,并将该哈希值与其 Cargo.lock、编译器和 LLVM 版本、构建日期等关联起来。这将是一个出色的 Cargo 包装器或插件。既然这可以通过一个 5 行的 shell 脚本完成,编写该工具就留给读者作为练习。
### 这会影响可复现构建吗?
该数据格式专门设计为不破坏可复现构建。它不包含时间戳,并且生成的 JSON 经过了排序,以确保在多次编译之间是相同的。如果说有什么影响的话,这实际上*有助于*可复现构建,因为您现在知道了给定二进制文件的所有版本。
### 这会泄露任何敏感信息吗?
不会。所有 URL 和文件路径都经过编辑,但 crate 名称和版本按原样记录。目前,panic 消息已经披露了所有这些信息甚至更多。此外,您很可能在法律上也有义务披露特定开源 crate 的使用情况,因为 MIT 和许多其他许可证都有此要求。
### 记录编译器版本呢?
编译器本身从 v1.73 及更高版本开始[嵌入了它](https://github.com/rust-lang/rust/pull/97550)。
在旧版本中,它已经存在于调试信息中。在 Unix 上,您可以运行 `strings your_executable | grep 'rustc version'` 来查看它。
### 跟踪静态链接的 C 库版本呢?
问得好。我认为目前它们没有以任何合理的方式暴露出来。这将是一个很好的补充,但对于初始发布来说不是必需的。我们可以稍后以向后兼容的方式添加它。采用 [`-src` crate 约定](https://internals.rust-lang.org/t/statically-linked-c-c-libraries/17175?u=shnatsel) 会使其自然发生,并且还会带来其他好处,因此这可能是最佳途径。
### 这能防止供应链攻击吗?
不能。请使用 [`cargo-vet`](https://github.com/mozilla/cargo-vet) 或 [`cargo-crev`](https://github.com/crev-dev/cargo-crev) 来防御此类攻击。
[软件物料清单](https://en.wikipedia.org/wiki/Software_supply_chain) (SBOM) 并不能防止供应链攻击。它们甚至不能用于评估此类攻击被发现后的影响,因为任何有价值的恶意库都会将自己从 SBOM 中移除。这几乎适用于所有语言和构建系统,而不仅仅是 Rust 和 Cargo。
在应对供应链攻击时,不要依赖 SBOM!
### 将此功能上游到 Cargo 中的阻碍是什么?
[关于 Cargo 自身此功能的 RFC](https://github.com/rust-lang/rfcs/pull/2801) 已被 Cargo 团队[推迟](https://github.com/rust-lang/rfcs/pull/2801#issuecomment-2122880841),直到[更基础的 SBOM RFC](https://github.com/rust-lang/rfcs/pull/3553) 完成。
该 RFC 现已实现,并可通过[不稳定特性](https://doc.rust-lang.org/cargo/reference/unstable.html#sbom) 使用。这为再次提交将此功能引入 `cargo` 本身的 RFC 敞开了大门。
标签:AI工具, Cargo插件, Claude, CVE检测, DevSecOps, ELF, Homebrew安装, Rust, SBOM, WebAssembly, 上游代理, 二进制分析, 云安全监控, 云安全运维, 依赖管理, 可审计性, 可视化界面, 嵌入式数据, 数据集, 文档安全, 生产环境安全, 硬件无关, 网络流量审计, 跌倒检测, 软件物料清单, 通知系统, 通知系统, 零开销, 静态分析