differential-review:Trail of Bits 把 PR 安全差异审查写成可执行流程

前言

给 PR 做安全审查时,常见做法是打开 diff,扫一遍新增逻辑,再凭印象判断「改动小、影响面可控」。这一步很容易漏掉两件事:被删掉的那几行当初为什么存在;改动的函数在仓库里到底有多少调用方。

前者需要 git blame / git log -S,否则一次「重构删校验」可能把半年前的 CVE 修复一并抹掉。后者需要定量数调用方,否则一个校验函数的签名变化,会沿着调用链扩散到意料之外的模块。Trail of Bits 把这条审计习惯写成了 Agent Skill differential-review:不按 PR 行数决定认真程度,而按风险等级、git 历史和爆炸半径决定分析深度,并强制落一份带证据的 Markdown 报告。

这是什么

一句话定位:differential-review 对 PR、commit 和 diff 做安全导向的差异审查——按仓库规模自适应分析深度,用 git 历史补上下文,计算改动的爆炸半径,检查测试覆盖缺口,并生成完整的 Markdown 报告。

它由 Trail of Bits 维护,放在 trailofbits/skills 插件市场的 Code Auditing 分类里。插件作者署名为 Omar Inuwa,仓库中 .claude-plugin/plugin.json 当前版本号为 1.1.1。源码目录:

https://github.com/trailofbits/skills/tree/main/plugins/differential-review/skills/differential-review

官方描述与 GitHub 上的 SKILL.md、插件 README、文档站 Differential Review 一致:针对代码变更做安全审查,检测安全回归,量化爆炸半径,找出被改代码缺测试的地方。

它基于通用 SKILL.md 格式,因此在 Claude Code、Codex CLI,以及能发现 Agent Skill 目录的 Cursor 等工具里都可以加载。作为 Claude Code 插件时,还附带斜杠命令和 adversarial-modeler 子代理;只拷贝 SKILL.md 时,不一定带上这两项,以实际安装方式为准。

工作流按 git diff 走,并不绑定单一语言。配套的 patterns.md 和示例以智能合约(Solidity)居多;methodology.md 里评估仓库规模的命令会统计 .sol / .rs / .go / .ts 文件数。审查 Web 服务、Rust 或 Go 仓库时,风险分类和阶段流程仍然适用,漏洞模式清单则要按语言自行对照,不要把 Solidity 的 onlyOwner 检测原样套到别的栈上。

核心功能与亮点

根据 SKILL.mdmethodology.mdadversarial.mdreporting.md 和插件 README,能力可以收成下面几条。文档采用渐进披露:入口文件只保留速查表和决策树,按阶段再加载对应长文,避免一次塞进全部方法论。

1. 按风险分流,不按 diff 大小

Skill 把「小 PR 可以快速过」列为必须拒绝的合理化借口,理由写在表里:Heartbleed 也只有两行。分类标准是风险,不是行数。

风险 触发条件
HIGH 鉴权、密码学、外部调用、价值转移、校验被删除
MEDIUM 业务逻辑、状态变更、新增公开 API
LOW 注释、测试、UI、日志

文档另外写明:重构在被证明为 LOW 之前,按 HIGH 分析。 重构经常破坏不变量。

仓库规模决定分析策略,与风险分类是两套轴:

规模 策略 做法
SMALL(少于 20 个文件) DEEP 读全部依赖,完整 git blame
MEDIUM(20–200) FOCUSED 一跳依赖,优先文件
LARGE(200+) SURGICAL 只走关键路径

小仓库可以深挖;大仓库的鉴权重写则只切关键路径,并建议先跑同市场里的 audit-context-building 建基线。

2. 用 git 历史抓安全回归

Phase 1 要求对照基线版本和当前版本读每个改动区,并对被删除的代码git blame / git log -S:这段代码何时加入、提交说明写了什么、是不是安全修复。

立即升级的红旗包括:

  • 删除来自带 securityCVEfix 的提交
  • 访问控制修饰符被拿掉(例如 onlyOwner,或 internal 改成 external
  • 校验被删且没有替代
  • 新增外部调用但没有检查
  • 爆炸半径 50+ 调用方,同时属于 HIGH 风险改动

文档给过一类典型回归:注释写着「Security fix: validate length to prevent overflow (CVE-…)」的长度校验,在「为了性能重构」时被删掉。git blame 能把它连回当初的 CVE 修复提交;只看新代码,往往看不出这是回归。

检测思路来自 patterns.md,例如:

# 曾经因安全原因删掉、现在又出现的模式
git log -S "pattern" --all --grep="security\|fix\|CVE"

# diff 里被删掉的 require / assert / revert
git diff <range> | grep "^-" | grep -E "require|assert|revert"

3. 定量计算爆炸半径

Phase 3 要求按被改函数的调用次数量化影响,而不是口头说「影响面不大」:

调用次数 爆炸半径
1–5 LOW
6–20 MEDIUM
21–50 HIGH
50+ CRITICAL

优先级矩阵把「改动风险 × 爆炸半径」合成 P0/P1/P2。HIGH 风险且 CRITICAL 爆炸半径要深挖并读全依赖;MEDIUM 风险但调用方很多,也要把调用方纳入分析。methodology.md 里的计数示例是用 grep 统计函数名出现次数,智能合约场景按 .sol 过滤。

4. 缺测试会抬高风险评级

Phase 2 把测试缺口写成风险规则,而不是「测试是测试同学的事」:

  • 新增函数且没有测试:MEDIUM 升为 HIGH
  • 改了校验但测试没动:HIGH
  • 复杂逻辑(超过 20 行)且没有测试:HIGH

报告里要列出未覆盖的函数,并据此决定是否建议卡住合并。

5. HIGH 风险要做对抗建模,并强制写报告

完整流程是 Pre-Analysis + Phase 0 到 Phase 6:

Pre-Analysis → Phase 0: Triage → Phase 1: Code Analysis → Phase 2: Test Coverage
                     ↓                    ↓                        ↓
Phase 3: Blast Radius → Phase 4: Deep Context → Phase 5: Adversarial → Phase 6: Report

Phase 5 要求给出具体攻击者模型(谁、有什么权限、从哪个接口进来),而不是「可能存在风险」。可利用性按 EASY / MEDIUM / HARD 评级。插件里的 adversarial-modeler 代理专门做这一步,只应在 HIGH 风险改动上启用。

Phase 6 强制生成 Markdown 文件,禁止只在对话里口头说明。报告固定九段:执行摘要(含 APPROVE / REJECT / CONDITIONAL)、变更说明、高危发现、测试覆盖、爆炸半径、历史上下文、建议、方法论与局限、附录。每条高危发现要带文件行号、commit、爆炸半径、测试覆盖、攻击场景和建议修复。

输出文件名格式为 <项目>_DIFFERENTIAL_REVIEW_<日期>.md,文档示例是 VeChain_Stargate_DIFFERENTIAL_REVIEW_2025-12-26.md。写入优先级:当前仓库工作目录 → 用户 Desktop → ~/.claude/skills/differential-review/output/。写文件失败时才退回对话,并提示手工保存。

五条原则写在入口文件里:Risk-First、Evidence-Based、Adaptive、Honest(写明覆盖范围和置信度)、Output-Driven。

安装与启用

Claude Code

官方 marketplace 安装分两步。先加入 Trail of Bits 插件市场:

/plugin marketplace add trailofbits/skills

再安装本插件:

/plugin install trailofbits/skills/plugins/differential-review

也可以先执行 /plugin menu 浏览后再装。/plugin 是 Claude Code 里的命令,不是系统 shell。文档站提醒:没加 marketplace 之前,单个插件不会出现在菜单里。

Quick Start 里的调用示例是:

/diff-review

插件命令文件 commands/diff-review.md 的 name 为 trailofbits:diff-review,参数约定为:

/trailofbits:diff-review <pr-url|commit-sha|diff-path> [--baseline <ref>]

Target 必填,可以是 PR 地址、commit SHA 或 diff 路径;--baseline 可选,用来指定对比基线。两条写法指向同一条命令,以当前 Claude Code 插件菜单里显示的名称为准。

Codex CLI

仓库 README 写明 Codex 可以直接加载 Claude 的 marketplace,不需要额外的 sidecar 元数据:

codex plugin marketplace add trailofbits/skills
codex plugin list
codex plugin add differential-review@trailofbits

最后一条里的插件名与仓库中 plugins/differential-review 目录名一致。

通用 Skill 安装(Cursor 等)

officialskills.shskills.sh 上的命令是:

npx skills add https://github.com/trailofbits/skills --skill differential-review

这条命令按 Agent Skills 的通用目录约定,把 SKILL.md 装进当前工具使用的 skills 路径。装好后直接描述审查任务即可。第三方目录上的安装次数、扫描分数不是官方数据,安装命令以 GitHub README 和上述目录页为准。

Skill 声明的工具权限是 ReadWriteGrepGlobBash,审查过程会跑 git / gh 和搜索命令。需要在有仓库历史的 git 工作副本里使用,并保证助手有执行这些工具的权限。

典型用法示例

下面提示词和命令均来自官方 SKILL.md、插件 README、methodology.md 和文档站,可按仓库现状复现。

1. 用自然语言触发,指向一段 diff

插件 README 的示例:

Review the security implications of this PR:
git diff main..feature/auth-changes

中文环境下可以说:

请用 differential-review,对 main..feature/auth-changes 做安全差异审查。
先按文件做风险分级,对 HIGH 风险文件跑完整流程(含 git blame 和爆炸半径),
最后把报告写到 Markdown 文件,不要只在对话里给结论。

2. 摄入阶段:把变更集摸清楚

methodology.md 要求先提取变更,再评估规模、给每个文件打风险分:

# commit 范围
git diff <base>..<head> --stat
git log <base>..<head> --oneline
git diff <base>..<head> --name-only

# PR
gh pr view <number> --json files,additions,deletions

3. 小 PR 快速分流(官方 Quick Triage)

输入:5 个文件的 PR,其中 2 个 HIGH、3 个 LOW。策略只用入口文件的 Quick Reference:

  1. 按文件分级
  2. 只深挖 2 个 HIGH 文件
  3. 对被删代码做 git blame
  4. 生成精简报告

文档给出的耗时大约是 30 分钟。即使走快速分流,碰到上文红旗仍要做对抗分析,不能因为「文件少」而跳过。

4. 中等仓库的标准审查

输入:约 80 个文件、12 处 HIGH 风险改动。策略为 FOCUSED:

  1. HIGH 文件走完整流程
  2. MEDIUM 做表面扫描
  3. LOW 跳过
  4. 按九段结构出完整报告

文档给出的耗时大约是 3–4 小时。自然语言可以写成:

Perform security review of PR #123 with full blast radius analysis

5. 大型关键改动:鉴权重写

输入:约 450 个文件、鉴权系统重写。策略为 SURGICAL,并串联 audit-context-building

  1. 先在基线 commit 上建上下文(不变量、信任边界、校验模式、调用图)
  2. 只深挖鉴权相关改动
  3. 算爆炸半径
  4. 做对抗建模
  5. 出完整报告

文档给出的耗时大约是 6–8 小时。基线分析示例:

git checkout <baseline_commit>
# 若已安装 audit-context-building
# Solidity 示例:
# audit-context-building --scope packages/contracts/contracts --focus invariants,trust-boundaries,validation-patterns,call-graphs,state-flows

分析完基线后再切回 head 看 diff。没有 audit-context-building 时,文档要求用 Read / Grep 手工做同样的行级追踪,而不是跳过 Pre-Analysis。

6. 审查结束后转成审计报告

同市场的 issue-writer 可以把差异审查报告转成给非技术干系人看的审计文档:

issue-writer --input DIFFERENTIAL_REVIEW_REPORT.md --format audit-report

文档站还提到可用 fp-check 对审查中的疑似漏洞做误报核对。这些都是独立插件,需要另行安装。

适用场景与注意事项

适合

  • 合并前对 PR / commit / diff 做安全审查
  • 怀疑改动把旧的安全修复又加了回来
  • 需要定量评估「这个函数一改,会波及多少调用方」
  • 被改代码缺测试,要把缺口写进合并决策
  • 鉴权、支付、外部调用、智能合约可见性这类高风险改动,需要对抗场景而不是笼统评论

官方文档举过的触发场景包括:鉴权系统重写合入 main 之前;被广泛调用的校验函数被删除;智能合约访问控制修饰符从 internal 改为 external;对 5 文件 PR 做分流,标出需要深挖的文件;生成绑定到具体行号和 commit 的证据报告。

明确不要用

  • 从零开始的绿场代码(没有基线可对比)
  • 纯文档改动
  • 格式化 / lint 这类外观改动
  • 用户只要口头摘要、并接受相应风险

这些情况文档要求改走普通代码审查。

使用上的限制

  1. 没有 git 历史就发挥不出主场。 浅克隆、squash 后丢失中间提交、或审查对象根本不在 git 里时,blame 和回归检测会明显变弱。Skill 把「git 历史太花时间」列为禁止跳过的借口。
  2. 诚实写覆盖范围。 原则里要求写明分析了哪些文件、LOW 是否被排除、置信度是 HIGH 还是 MEDIUM。时间不够时不要声称做了全文分析。
  3. 发现必须可定位。 要有行号、commit、具体攻击步骤;「输入校验可能被绕过」这类句子在质量清单里不算合格发现。
  4. 报告必须落盘。 只在聊天窗口里给结论,等于没有交付物。
  5. Solidity 模式不能当通用漏洞百科。 patterns.md 覆盖回归、重入、访问控制、溢出、未检查返回值、时间戳依赖等,示例以合约为主。审查其他语言时沿用阶段流程,模式清单要换。
  6. 子代理和斜杠命令取决于安装路径。 marketplace / 插件安装会带上 commands/diff-review.mdagents/adversarial-modeler.md;只用 npx skills add 同步 Skill 目录时,通常只有 SKILL.md 和同目录的 methodology / adversarial / reporting / patterns。提示词里应写明「按 differential-review 的完整阶段出报告文件」。
  7. 许可是 CC BY-SA 4.0。 仓库根 README 声明整套 skills 按 Creative Commons Attribution-ShareAlike 4.0 授权。

小结

differential-review 做的事情很具体:把安全团队在差异审查里反复强调的步骤——风险分级、git blame、爆炸半径、测试缺口、对抗场景、落盘报告——写成 Agent 可执行的流程。它解决的不是「AI 会不会看 diff」,而是默认审查会跳过删除代码的历史、不会定量数调用方、也不留下可归档的证据。

官方地址:

  • Skill 目录:https://github.com/trailofbits/skills/tree/main/plugins/differential-review/skills/differential-review
  • 插件说明:https://github.com/trailofbits/skills/tree/main/plugins/differential-review
  • Trail of Bits 技能页:https://trailofbits.com/skills/differential-review/
  • 文档站:https://trailofbits-skills.mintlify.app/plugins/differential-review
  • officialskills.sh:https://officialskills.sh/trailofbits/skills/differential-review
  • 市场仓库:https://github.com/trailofbits/skills
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜