Booyaka101/rust-symbol-audit
GitHub: Booyaka101/rust-symbol-audit
一个 GitHub Action,对 Rust 依赖升级 PR 进行符号级能力 diff、编译时代码审查、供应链溯源和安全公告检查,并通过有状态审查棘轮机制实现可靠的合并门禁。
Stars: 0 | Forks: 0
# rust-symbol-audit
[](https://github.com/Booyaka101/rust-symbol-audit/actions/workflows/tests.yml)
[](https://github.com/Booyaka101/rust-symbol-audit/releases)
[](https://github.com/marketplace/actions/rust-symbol-audit)
[](LICENSE)
一个 GitHub Action,将 Rust 依赖升级转化为**您可以真正设卡的 capability-creep 审查**。
它回答了版本号无法回答的问题:*这次升级 —— 该 crate 是否开始打开 sockets,生成进程,在我的构建机器上运行代码,更改了发布者,或者携带了已知漏洞?*
## 五条通道
1. **Symbols** — 构建新旧版本,对比 **v0-demangled** 的 `.rlib` 符号,并标记新引用的敏感 API(`std::process::Command`、`TcpStream`、`std::fs`、`env::var`、类似于 secret 的名称、`reqwest`/`rustls`…)。
2. **Compile-time surface** — 新增或修改的 **`build.rs`**,切换到 **`proc-macro = true`**,或者新的 **`links =`** 原生库。这些是*在编译时于您的构建机器上*运行的代码 —— 并且评论会展示**实际的 build-script 差异**,而不仅仅是“它变了”。Symbol 对比对此视而不见。
3. **Dependency tree** — 升级**新拉入到您构建中的** crates,突出显示那些具有已知网络 / 进程 / 加密 / FFI 能力的 crates。
4. **Provenance** *(网络)* — 通过 crates.io API:由**不同账号**发布的版本、**没有源代码仓库**的 crate,或者**被撤回 (yanked)** 的版本。这是真实供应链攻击最初期的模样。
5. **Advisories** *(网络)* — 通过 OSV.dev (RustSec):针对确切新版本的已知漏洞。
## 棘轮机制 —— 为什么您可以一直开启它
在每次 PR 中对升级重新报警的启发式方法会被静音处理。rust-symbol-audit 是**有状态的**:在 `.rust-symbol-audit/reviews.toml` 中签署放行某个版本一次,未来的审计就会对该版本保持绿色通过 —— 因此每一次红色警报都是真正的**新增且未审查的**内容。这就是让 `fail-on` 足够可靠以至于能阻断合并的原因。
```
# .rust-symbol-audit/reviews.toml — capability 签核
[[review]]
crate = "reqwest"
version = "0.12.0"
reviewed_by = "alice"
notes = "http client; network capability expected"
```
PR 评论中包含一个可复制粘贴的**签署放行代码片段 (sign-off snippet)**,适用于每个未审查的 crate(或者运行 `scripts/review.sh `),因此批准一次升级只需一次粘贴。关键是,签署放行**仅**抑制能力相关的通道 —— 后续的**安全公告或 provenance 变更绝不会因为旧的审查记录而被隐藏**。
## 用法
将 [`examples/pr-audit.yml`](examples/pr-audit.yml) 复制到
`.github/workflows/pr-audit.yml`:
```
on:
pull_request:
paths: ["Cargo.lock"]
permissions:
contents: read
pull-requests: write # post/update the comment
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: booyaka101/rust-symbol-audit@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fail-on: "none" # or critical/high/medium to block merges
```
要自动合并无聊的 Dependabot 升级并拦下有风险的升级,请参阅
[`examples/auto-merge.yml`](examples/auto-merge.yml)(基于 `recommendation` 输出为 GitHub 自动合并设卡)。
### 输入
| 输入 | 默认值 | 描述 |
|---|---|---|
| `github-token` | — | 通常是 `secrets.GITHUB_TOKEN`。用于发布/更新评论。 |
| `max-crates` | `10` | 最多审计这么多数量的变更 crates;其余的将被列为“未审计”。 |
| `fail-on` | `none` | 在 `medium`/`high`/`critical` 级别使检查失败。`none` = 仅提供公告建议。 |
| `config` | `.rust-symbol-audit.toml` | 用于抑制已知良性信号的允许/忽略规则。 |
| `reviews` | `.rust-symbol-audit/reviews.toml` | 审查账本(即棘轮机制)。 |
| `check-provenance` | `true` | 查询 crates.io 以获取发布者/仓库/撤回 (yank) 变更(需要网络)。 |
| `check-advisories` | `true` | 查询 OSV.dev 以获取 RustSec 公告(需要网络)。 |
### 输出
| 输出 | 描述 |
|---|---|
| `changed` | 是否有任何 crate 版本在 `Cargo.lock` 中发生了变更。 |
| `tier` | 最高风险等级:`critical`/`high`/`medium`/`none`。 |
| `flagged` | 带有被标记信号的 crates,以逗号分隔。 |
| `build-script-changes` | 构建脚本被新增/修改的 crates 数量。 |
| `advisories` | 发现的已知 RustSec/OSV 公告数量。 |
| `recommendation` | `auto-merge`(等级为 none)或 `review` —— 据此为 Dependabot 自动合并设卡。 |
| `report` | 机器可读的 `audit-report.json` 证据文件的路径。 |
### 抑制误报 — `.rust-symbol-audit.toml`
参见 [`examples/rust-symbol-audit.toml`](examples/rust-symbol-audit.toml):
```
ignore_crates = ["libc", "windows-sys"] # never flag these
[allow]
reqwest = ["TcpStream", "hyper", "rustls"] # suppress these findings for this crate
```
`ignore`/`allow` 会永久静音某个信号;而**账本**一次只签署放行一个版本(并且依然会显示未来的安全公告)。如果表示“允许此 crate 永远拥有此能力”,请使用 `allow`;如果是表示“我审查了确切的这个版本”,请使用账本。
### 合规性 / SLSA 证据
每次运行都会写入 `audit-report.json`(包含总体结论 + 每个 crate 和通道的每项发现)并将其作为 workflow artifact 上传 —— 这就是该依赖项变更已被审查的记录。
## 在本地运行
需要 `rustup`/`cargo`、`rustfilt`(`cargo install rustfilt`)以及一个符号列举工具(GNU `nm`,或 `rustup component add llvm-tools` → `llvm-nm`,在 Windows 上会自动检测)。在 **Git Bash** 中:
```
bash test/run_local.sh # -> RESULT: 46 passed, 0 failed / ALL GREEN
```
将演练所有五个通道、账本棘轮机制、配置抑制、设卡、Dependabot 建议以及证据报告 —— 完全离线运行,使用测试夹具和模拟的 crates.io / OSV 响应(外加一次真实的 crates.io 升级)。有关真实 PR 的检查清单,请参阅 [`TESTING.md`](TESTING.md)。
## 能捕获和无法捕获的内容
**擅长捕获:** 开始直接调用 `std::net`/`process`/`fs` 的 crate;新增或修改的 **build script** / **proc-macro**(即使该 crate 无法作为 lib 构建时);新链接的**原生库**;依赖树中的**新 crates**;**发布者/仓库/撤回 (yank)** 状态的变更;新版本上的**已知安全公告**。
**遗漏 / 局限(静态分析固有的缺陷):** 通过从未在 crate 自身的 rlib 中实例化的泛型,或通过未更改的依赖项体现出的能力;运行时行为(它只读取表面接口,不进行沙盒隔离);无法独立构建的 crates(仅影响 symbol 通道 —— 其他通道仍然适用);网络通道需要网络连接,在离线状态下会优雅降级。可通过配置 + 账本调节以减少噪音。
## 分发的最佳第一步
发布到 **GitHub Marketplace**(安全类别),标语为*“一个针对 Rust 依赖 PR 的 capability-creep 分拣卡点 —— 带有您可以用来阻断合并的审查棘轮。”* 编译时代码通道和签署放行棘轮机制,正是仅提供 symbol 和仅提供 advisory 的工具所缺乏的具体抓手。
标签:GitHub Action, Rust, XSS, 代码审查, 依赖审计, 可视化界面, 安全门禁, 文档安全, 漏洞情报, 网络流量审计