前言¶
給 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.md、methodology.md、adversarial.md、reporting.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:這段代碼何時加入、提交說明寫了什麼、是不是安全修復。
立即升級的紅旗包括:
- 刪除來自帶
security、CVE、fix的提交 - 訪問控制修飾符被拿掉(例如
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.sh 與 skills.sh 上的命令是:
npx skills add https://github.com/trailofbits/skills --skill differential-review
這條命令按 Agent Skills 的通用目錄約定,把 SKILL.md 裝進當前工具使用的 skills 路徑。裝好後直接描述審查任務即可。第三方目錄上的安裝次數、掃描分數不是官方數據,安裝命令以 GitHub README 和上述目錄頁爲準。
Skill 聲明的工具權限是 Read、Write、Grep、Glob、Bash,審查過程會跑 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:
- 按文件分級
- 只深挖 2 個 HIGH 文件
- 對被刪代碼做 git blame
- 生成精簡報告
文檔給出的耗時大約是 30 分鐘。即使走快速分流,碰到上文紅旗仍要做對抗分析,不能因爲「文件少」而跳過。
4. 中等倉庫的標準審查
輸入:約 80 個文件、12 處 HIGH 風險改動。策略爲 FOCUSED:
- HIGH 文件走完整流程
- MEDIUM 做表面掃描
- LOW 跳過
- 按九段結構出完整報告
文檔給出的耗時大約是 3–4 小時。自然語言可以寫成:
Perform security review of PR #123 with full blast radius analysis
5. 大型關鍵改動:鑑權重寫
輸入:約 450 個文件、鑑權系統重寫。策略爲 SURGICAL,並串聯 audit-context-building:
- 先在基線 commit 上建上下文(不變量、信任邊界、校驗模式、調用圖)
- 只深挖鑑權相關改動
- 算爆炸半徑
- 做對抗建模
- 出完整報告
文檔給出的耗時大約是 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 這類外觀改動
- 用戶只要口頭摘要、並接受相應風險
這些情況文檔要求改走普通代碼審查。
使用上的限制
- 沒有 git 歷史就發揮不出主場。 淺克隆、squash 後丟失中間提交、或審查對象根本不在 git 裏時,blame 和迴歸檢測會明顯變弱。Skill 把「git 歷史太花時間」列爲禁止跳過的藉口。
- 誠實寫覆蓋範圍。 原則裏要求寫明分析了哪些文件、LOW 是否被排除、置信度是 HIGH 還是 MEDIUM。時間不夠時不要聲稱做了全文分析。
- 發現必須可定位。 要有行號、commit、具體攻擊步驟;「輸入校驗可能被繞過」這類句子在質量清單裏不算合格發現。
- 報告必須落盤。 只在聊天窗口裏給結論,等於沒有交付物。
- Solidity 模式不能當通用漏洞百科。
patterns.md覆蓋迴歸、重入、訪問控制、溢出、未檢查返回值、時間戳依賴等,示例以合約爲主。審查其他語言時沿用階段流程,模式清單要換。 - 子代理和斜槓命令取決於安裝路徑。 marketplace / 插件安裝會帶上
commands/diff-review.md和agents/adversarial-modeler.md;只用npx skills add同步 Skill 目錄時,通常只有SKILL.md和同目錄的 methodology / adversarial / reporting / patterns。提示詞裏應寫明「按 differential-review 的完整階段出報告文件」。 - 許可是 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