Cloudflare 開源的 security-audit-skill 是一套給 coding agent 用的安全稽核技能:它把「找漏洞」拆成偵察、覆蓋率導向狩獵、候選驗證、結構化輸出、獨立複核、產生報告六個階段,每個候選漏洞都要交給「不是發現它的那個 agent」想辦法反駁,只有真的越過信任邊界、有具體影響的才給嚴重性。目前 39,131 星、MIT 授權,是 Cloudflare 自家漏洞發現 harness 的種子版本。
如果你已經在用 Claude Code、Cursor、Codex 這類工具寫程式,這篇的價值不在「又一個 AI 工具」,而在它示範了一件更重要的事:怎麼樣讓 AI 的資安結論「可以被查證」,而不是一份看起來很專業的猜測。
為什麼這個技能值得花時間看
多數人對「AI 找漏洞」的印象是:把 repo 丟給模型,它回你一堆「可能存在 SQL injection」的段落。問題是那份清單通常不能拿去修東西——沒有行號、沒有攻擊路徑、沒有重現方式,而且充滿誤報。
security-audit-skill 的差別在於它是一份流程規定,不是一段提示詞。它在 SKILL.md 裡直接寫死「什麼不算漏洞」:
- 沒有具體受影響主體(principal)、資源、或安全結果的候選,不准標成 confirmed;
- 只是「少了縱深防禦」而前一層已經擋住的,不算漏洞,只能算加固建議;
- 嚴重性必須由「影響」推導,不能因為「偏離檢查清單」就給高分。
而且它的出身有點硬:這是 Cloudflare 那個「vulnerability harness」的起點。官方部落格說得很直白——他們一開始就是一個 約 450 行的 security-audit skill,先跑在單一 repo 上,一路調整 prompt 直到真的挖到 bug,後來才長成跨 128 個 repo 的 fleet 掃描系統。開源出來的這個版本,就是那個還沒長成系統之前的樣子。
一表看懂
| 項目 | 內容 |
|---|---|
| 倉庫 | cloudflare/security-audit-skill |
| 星數/Fork | 39,131 ★/2,438(2026-10-22 以 GitHub API 查詢) |
| 授權 | MIT |
| 建立時間 | 2026-06-18(與官方 harness 部落格同日) |
| 最近推送 | 2026-09-14 |
| 主要語言 | JavaScript(驗證器;主體是 Markdown 技能文件) |
| 安裝方式 | Skills CLI:npx skills add |
| 依賴 | 支援 tool use 與平行子代理的模型、Node.js(跑驗證器) |
| 必要條件 | OS 層級沙箱,否則不會執行目標程式碼 |
| 今日熱度 | GitHub Trending 當日 +2,979 星(2026-10-22 抓取) |
六個階段:它到底怎麼跑
這是全篇最值得記住的部分。技能的流程長這樣:
| 階段 | 產出 | 在做什麼 |
|---|---|---|
| 1. 偵察(Reconnaissance) | architecture.md、coverage-ledger.json | 自己有系統地畫出架構、信任邊界、輸入面、過往證據,並建立「覆蓋率帳本」 |
| 2. 覆蓋率導向狩獵(Hunting) | 各 hunter 的檢查紀錄 | 從帳本切出單位,分派隔離的 hunter,再用 coverage critic 找出沒被覆盖的角落 |
| 3. 候選驗證(Validation) | 候選清單 | 每個候選交給全新的 verifier,它的任務是「想辦法證明這是錯的」 |
| 4. 結構化輸出 | findings.json | 寫成 confirmed/needs_validation/rejected 三種判決,並用 schema 驗證 |
| 5. 獨立複核 | 修正後的紀錄 | 再開新的 agent 複核最終結論;有重大替換時,換另一個獨立 verifier 再驗 |
| 6. 產出報告 | REPORT.md、FINDINGS-DETAIL.md、NEEDS-VALIDATION.md | 從「已驗證的紀錄+覆蓋率帳本」推導報告,且不含任何對線上環境探測的指示 |
幾個藏在細節裡的設計,比流程本身更關鍵:
- 驗證者不能是發現者。 官方原則寫得很白:「the agent that checks a finding is never the agent that found it.」這是為了避免同一個推理路徑自我確認。
- 覆蓋率是顯性資產。
coverage-ledger.json由 parent agent 獨占寫入,每次有 agent 回報就更新。它讓「這次掃了哪些、哪些沒掃」變成可稽核的資料,而不是一句「應該差不多都看了」。 - 多次執行是加法。 同一 repo 重跑會讀先前的帳本與 findings,針對缺口補、把改過的原始碼重新驗證,而不是從零開始。
安裝:官方指令原文
技能用 Skills CLI 安裝(skills.sh),兩行就結束:
npx skills add https://github.com/cloudflare/security-audit-skill \
--skill security-audit
想裝在使用者層級(所有專案共用):
npx skills add https://github.com/cloudflare/security-audit-skill \
--skill security-audit \
--global
其他代理選擇、非互動安裝的參數,用 npx skills --help 查。裝好之後不需要記指令,用自然語言觸發就行。
三種觸發方式,但只有兩種模式
官方給的範例提示很樸素,貼進代理就能用:
security audit this codebase
find security vulnerabilities in ./src
do a security review, output to ~/audits/my-project
要注意的是它刻意分成兩種模式,而且預設是保守的那一個:
| 模式 | 什麼時候用 | 會做什麼 |
|---|---|---|
| Guidance(預設) | 問資安問題、看某段程式、triage 已知問題 | 只用相關章節回答,不會跑完六階段、不建目錄、不寫檔案 |
| Full audit | 明確要求「稽核/滲透測試整個 codebase」、要完整或 end-to-end 審查、要報告產出 | 跑完六階段,寫出所有檔案 |
原文的規定是:「Loading it does not authorize the complete audit workflow or file creation.」——載入技能不等於授權它開始跑全套。如果一句話兩種都說得通,它會先問你一個問題再動手。
Full audit 模式的輸出目錄預設是 ~/security-audit-skill/<repo-name>/run-<N>,N 自動取沒用過的流水號。要寫在目標 repo 裡,必須是你明確指定、而且 parent 確認整個目錄被版控忽略,否則會停下來要求給一個外部路徑——這條規定是為了避免稽核產物污染 repo。
三種 profile:quick/standard/deep
不是每次稽核都需要一樣的力氣,所以它有 profile 概念:
| Profile | 適用 | 行為差異 |
|---|---|---|
quick | 小目標、重跑、先看一眼 | 覆蓋單位粗化到「表面 × 邊界 × 攻擊類型」,只跑一輪 hunter+一次最終 critic;後續發現標為 deferred |
standard(預設) | 一般情況 | 照文件完整跑 |
deep | 高風險或大型目標 | 每個子系統與生命週期模式都切單位,critic 跑到乾淨為止,validation 與 record verification 各自獨立 agent,舊覆蓋單位再跑第二遍 |
Profile 只改變「廣度與冗餘」,不改變證據標準。文件寫得很清楚:候選門檻、原始碼/本地執行的邊界、needs_validation 紀律、schema 驗證、confirmed 的獨立複核,都不能因為選了 quick 就被縮掉。
另外有一個很實用的設計:預算是用「agent 呼叫次數」計價的。你可以在 run-metadata.json 裡設 budget,parent 會先保留「偵察 4 次+critic+至少 1 個 verifier」的額度,再決定能派幾個 hunter。如果預算連最低儲備都不夠,它會直接一個 agent 都不派,把狀態設成 incomplete 並告訴你原因——而不是硬跑一場假的稽核。
輸出長什麼樣
Full audit 會產出這些檔案,全部由 parent 獨占寫入:
| 檔案 | 內容 |
|---|---|
run-metadata.json | run_id、repo、target、source_ref、profile、scope、budget、執行政策、狀態 |
architecture.md | 架構、信任邊界、輸入面 |
coverage-ledger.json | 覆蓋率帳本(每個單位的狀態) |
findings.json | 三種判決的結構化結果 |
REPORT.md | 主報告 |
FINDINGS-DETAIL.md | 已確認漏洞的細節 |
NEEDS-VALIDATION.md | 被卡住、需要人補資料的候選 |
findings.json 只有三種判決,界線分得非常乾淨:
| 判決 | 條件 | 有沒有嚴重性 |
|---|---|---|
confirmed | 有完整原始碼追蹤路徑,加上有界觀察到的結果 | 有 |
needs_validation | 有具體未解事實擋住,假設停在原始碼層級 | 沒有(這點很重要:它不是「低信心的 confirmed」) |
rejected | 已被證偽的候選 | 沒有 |
一條 confirmed 紀錄必填的欄位有 13 個:verdict、fingerprint、title、description、root_cause、intended_behavior、trace、evidence、conditions、execution、remediation、severity、confidence。骨架大概長這樣:
[
{
"verdict": "confirmed",
"fingerprint": "src/api/export.ts:42:tenant-scope",
"title": "匯出 API 未檢查 tenant 邊界",
"description": "已驗證:跨租戶讀取 dummy 資料成功。",
"root_cause": "查詢條件只帶 resource_id,未帶 tenant_id。",
"intended_behavior": "每個查詢都必須以呼叫者的 tenant 為主鍵。",
"trace": [
{ "kind": "entrypoint", "file": "src/api/export.ts", "line": 42, "scope": "router.export", "description": "未驗證 tenant 的入口" },
{ "kind": "sink", "file": "src/db/export.ts", "line": 88, "scope": "buildQuery", "description": "缺少 tenant 條件" }
],
"evidence": [
{ "file": "src/db/export.ts", "line": 88, "description": "WHERE 子句僅含 resource_id" }
],
"conditions": "需要已登入的低權限帳號,攻擊者需知道他人的 resource_id。",
"execution": {
"attacker_perspective": "以 tenant A 的帳號請求 tenant B 的資源",
"payloads": ["/api/export?resource_id=t2-001"],
"instructions": ["在沙箱啟動本機服務", "以 dummy 帳號 A 呼叫上述路徑"],
"observed_result": "回應 200 並回傳 tenant B 的 dummy 匯出檔"
},
"remediation": "在 buildQuery 強制注入呼叫者的 tenant_id,並補一條跨租戶拒絕的迴歸測試。",
"severity": {
"likelihood": { "score": "high", "reason": "只需低權限帳號與一個可猜測的 ID" },
"impact": { "score": "high", "reason": "跨租戶讀取真實資料,屬明確的邊界突破" },
"overall_severity": "high"
},
"confidence": { "score": "high", "reason": "已有有界本地重現結果" }
}
]
嚴重性分五級,判準寫在 SKILL.md 裡(不是感覺):
| 等級 | 判準 |
|---|---|
| critical | 未經驗證的攻擊者取得程式碼執行、完整資料庫存取,或可接管任意帳號 |
| high | 完全打穿某個明確安全控制且後果真實(驗證繞過、跨租戶讀寫、儲存型 XSS 影響他人、已驗證身分的程式碼執行) |
| medium | 真實邊界突破,但爆炸半徑有限、前置條件罕見 |
| low | 洩漏非機密的內部資訊,或需長期投入才有微小成果 |
| informational | 已確認但影響極小,主要價值是當成更大漏洞的前置條件 |
驗證器:唯一「可機器檢查」的部分
這是這個技能最實用的地方——它不是只給你一份 Markdown,而是附了兩支零依賴驗證器,用 Node.js 就能跑:
node <skill-dir>/validate-findings.cjs <output-dir>/findings.json
node <skill-dir>/validate-coverage-ledger.cjs <output-dir>/coverage-ledger.json
validate-findings.cjs 會照 report-schema.json 檢查(自己實作 schema 直譯器,不裝任何套件),validate-coverage-ledger.cjs 檢查覆蓋率帳本的結構。規則是:帳本建立後驗一次、之後每次更新再驗;findings 在第 4 階段驗一次,第 5 階段每次替換後再驗。
這代表你可以把它塞進 CI:「報告存在」不算通過,「報告通過 schema」才算。 這兩支腳本也有自己的測試檔(.test.cjs),這在 AI 工具裡算少見的誠實。
沙箱:沒有它,技能會拒絕執行目標程式碼
這是很多人會忽略、但實務上最卡的一關。技能的規定是:只有在 OS 層級沙箱裡,才允許跑目標自己的 build、測試、瀏覽器、模擬器、fuzzer,而且沙箱必須同時滿足:
- 對外網路關閉(需要本地 client/server 時只用隔離的 loopback);
- 環境變數從白名單重建(空的 HOME、暫存、cache);
- 目標與工具鏈唯讀,目標程式只能寫進被分派的
scratch/; - 明確的 CPU、記憶體、process 數、檔案大小、磁碟、wall-clock 上限。
做不到怎麼辦?文件寫得很硬:不要執行,把缺的沙箱能力當成 needs_validation 的 blocker 回報,並給一份安全的驗證計畫。另外原始碼檢視全程唯讀,不准對已部署的端點、共享基礎設施、正式身分、別人的資料做探測。
換句話說,這個技能在設計上就把「AI 亂打你的 production」這條路堵掉了——代價是你得先準備好沙箱環境。
五個要講清楚的限制
一篇只講優點的工具文沒有價值,這幾個限制必須寫在前面:
- 單次執行只抓到約一半的漏洞。 官方在 README 的設計原則裡自己承認:在他們的測試裡,單次 run 大約只找到「多次 run 加總」的一半,而且找到的偏向比較簡單、不那麼隱蔽的那些。部落格講得更白:「一旦你的流程變成『跑十次再人工比對』,你就該開始考慮真正的 harness 了。」
- 128 個 repo 那個數字不是這支技能的成績。 那是 Cloudflare 內部 harness 六週長出來的規模(含跨 repo 依賴追蹤、SQLite 持久化、sibling forking 等)。開源版是單一 repo 的起點,別把它當企業級掃描器。
- 沒有公開的第三方獨立評測。 星數 39,131 是社群關注度,不等於「實測優於某某商業 SAST」。文章裡所有效能數字都是官方自述。
- 吃資源,也吃模型品質。 它要求模型支援 tool use 與平行子代理,一場 standard 或 deep 稽核會派出大量 agent;部落格提到他們把每個 agent 的 context 壓在視窗的 25% 以下才不會開始幻覺。模型越弱,誤報越多、驗證輪數越長。
- 它只描述修法,不改你的程式碼。 這是刻意設計(稽核不該動目標原始碼),所以「找到→修好」之間仍然要你自己接手。
跟其他做法怎麼選
| 做法 | 擅長 | 不擅長 |
|---|---|---|
| 傳統 SAST/SCA(規則式、依賴掃描) | 快、可重現、CI 友善、已知 CVE 覆蓋好 | 業務邏輯漏洞、跨模組信任邊界、需要「理解意圖」的問題 |
| 商業 AI code review(PR 留言型) | 與 PR 流程整合、即時回饋 | 通常只看 diff,缺少整體威脅模型;證據鏈較弱 |
| 這個 skill(full audit) | 有威脅模型、有覆蓋率帳本、有獨立驗證與可機器檢查的輸出 | 慢、貴、需沙箱;單次覆蓋不完整,要重跑 |
| 委外滲透測試 | 人類創意與經驗、合規報告 | 貴、週期長、頻率低 |
實務上最合理的組合是:SAST/SCA 當每天的門禁,這個 skill 當「重大改版前或高風險模組」的深度檢查,正式上線前再排一次人工滲透測試。
誰適合、誰不需要
適合:正在用 Claude Code/Cursor/Codex 的後端或全端工程師;要對自家服務做定期內部稽核的小團隊;想學「怎麼把 AI 稽核流程做得可查證」的人(就算不裝,SKILL.md 那 190 行的流程規定本身就值得讀)。
不需要:只是想知道「這段 code 有沒有明顯問題」的人(guidance 模式就夠,別開 full audit);沒有沙箱環境又打算讓它跑 build 的人(它會拒絕,你也別硬開);期待它取代 SAST 或滲透測試的人。
站內延伸閱讀
- Open Code Review 完整教學 2026:阿里巴巴開源的 AI 程式碼審查 CLI
- Agent Skills 完整教學:Addy Osmani 開源專案,讓 Claude Code、Cursor 自動遵循工程紀律
- MCP 完整教學 2026:Model Context Protocol 入門到實戰
- llms.txt 與 agent 供應鏈:AI 爬蟲時代的新入口
- Claude Skills 最佳實務 2026:官方 7 條新規則
資料來源與查證方法
- GitHub 倉庫:cloudflare/security-audit-skill(README、
skills/security-audit/SKILL.md、report-schema.json、validate-findings.cjs、VALIDATION-AND-REPORTING.md皆直接讀取原始檔) - 星數/Fork/授權/建立與推送時間:
api.github.com/repos/cloudflare/security-audit-skill,查證時間 2026-10-22(網頁顯示的星數可能是快取,以 API 為準) - 當日熱度 +2,979 星:GitHub Trending 頁面(
github.com/trending)2026-10-22 抓取 - 背景與實測數字(450 行起家、128 個 repo、單次約抓到一半、context 壓在 25% 以下、SQLite 依
(run_id, repo, stage)持久化):Cloudflare 官方部落格 Build your own vulnerability harness(2026-06-18,Dan Jones、Alexandra Godoi、Grant Bourzikas) - 未實測的部分:本文沒有實際安裝此技能、也沒有對任何 repo 跑過一場稽核(全程以官方原始檔與部落格取材)。因此「跑起來效果如何」屬於官方自述,尚未經本文獨立驗證。
