一、导读
2026 年 10 月 20 日的 GitHub 日榜上,cloudflare/security-audit-skill 以单日 +1,680 星排在总榜第三,是榜单里唯一一个「仓库里没有一行扫描器代码」的安全项目。它是一个编码智能体技能(Agent Skill):装进 Claude Code、Codex 这类支持子智能体的工具后,一句「security audit this codebase」就会触发六个阶段、数十个相互隔离的子智能体协同完成一次源码级安全审计。更重要的是它的出身——Cloudflare 在 2026 年 6 月的博客《Build your own vulnerability harness》里说,自家扫过 128 个仓库、产出 7,245 条可操作发现的漏洞猎取平台,就是从这个单仓库技能长出来的。本文拆解它如何用一套 Markdown 契约把「大模型会幻觉、会丢上下文、会把检查清单偏差当漏洞」这些老问题关进笼子,以及它在 LLM 应用审计上的独特价值。
二、项目速览
| 维度 | 信息(截至 2026-10-21) |
|---|---|
| 仓库 | cloudflare/security-audit-skill,MIT 许可,2026-06-18 首次提交 |
| 规模 | 33,494 星、2,103 fork;日榜 +1,680(10-20),7 月 Semgrep 评测时仅约 2,000 星 |
| 构成 | 22 个文件:1 份 SKILL.md 主契约 + 5 份流程文档 + 10 份攻击类「伴侣文档」+ 1 份 JSON Schema + 2 个零依赖 Node 校验器及其测试 |
| 代码量 | 校验器 validate-findings.cjs 773 行、validate-coverage-ledger.cjs 872 行,65 个测试用例 |
| 维护 | 主维护者 Dan Jones(Cloudflare),3 位贡献者;最近一次提交 2026-09-14,v2 重构 PR #12 于 09-10 合入(+4,792 / −701 行) |
| 运行要求 | 支持工具调用与并行子智能体的编码智能体;Node.js 跑校验器;执行目标代码必须有 OS 级沙箱 |
| 安装 | npx skills add https://github.com/cloudflare/security-audit-skill --skill security-audit |
| 产物 | architecture.md、coverage-ledger.json、findings.json、REPORT.md、FINDINGS-DETAIL.md、NEEDS-VALIDATION.md |
三、为什么是它
这个仓库经历了两次爆发:第一次是 2026 年 9 月 17 日登上 Hacker News 首页(213 分、38 条评论),当时它刚完成 v2 重构;第二次就是本周,过去七天里 X、Instagram、YouTube Shorts 上出现一批「Cloudflare 开源了自家漏洞猎取平台的种子技能」的传播帖,把三个月前的项目重新推上日榜。表面动因是「Cloudflare 出品、免费、一条命令」,但它能被 Semgrep 列为「LLM 技能增强」路线的代表,靠的是三个更结实的原因。
第一,它是极少数公开了「生产验证数据」的审计提示工程。Cloudflare 博客给出的数字链是:128 个仓库六周跑出 20,799 条原始候选,验证后剩 12,057 条,去重砍掉 5,442 条,再剔除 1,154 条错路由或低风险项,最终 7,245 条可操作发现;验证阶段的拒绝率从 40% 降到 11%,高完整度发现占比从 35% 升到 58%。数字来自这个技能的「长大版」,但足以说明方法论经过了真实规模的锤炼。
第二,它正面回答了「智能体做安全审计到底靠什么保证质量」。大多数同类项目把质量寄托在模型能力上,它把质量拆成三个可机器检查的契约:覆盖账本决定「查过哪里」、三元裁决决定「什么算发现」、独立验证决定「谁有资格说确认」。v2 重构的 PR 描述里,作者用 gpt-5.6-sol 跑了两次端到端内部审计,校验器全部通过,且运行「正确地自我报告了预算受限的部分覆盖」——这种「宁可报告不完整也不虚报完整」的纪律,恰恰是传统 LLM 工具最缺的。
第三,它的 AI-AND-LLM.md 伴侣文档把 LLM 应用安全写成了可执行的猎取方法:提示注入、记忆投毒、MCP 身份混淆、工具参数注入等 14 个攻击类,每一类都配「什么不算发现」的反向判据。对正在构建智能体产品的团队,这份文档本身就有独立价值。
四、架构原理
4.1 整体架构:一个编排者、两种子智能体、六个阶段

技能把所有角色抽象成平台无关的术语:Parent 是协调整个运行、唯一有权写共享文件的编排者;research 子智能体负责只读的源码探索与事实核验;general 子智能体负责更宽的调查与受限的本地执行。六个阶段串成一条流水线,每个阶段的输入输出都是磁盘上的具名文件。
flowchart TB
T["目标仓库(只读)"] --> P1
subgraph P1["阶段 1 侦察:4 个 research 并行"]
R1["1a 产品 / 技术栈 / 本地运行"]
R2["1b 主体 / 权限 / 控制点"]
R3["1c 入口面 / 派生副本 / 汇点"]
R4["1d 本地执行与部署可见性"]
end
P1 --> A["architecture.md(约 1000 词上限)"]
A --> L["coverage-ledger.json 确定性覆盖账本"]
L -->|planned 单元| H["阶段 2 猎手 general × N 只写自己的 scratch/"]
H -->|单一 JSON 结果| L
L --> C["覆盖评论员 research:missing_units / reassign_ids"]
C -->|新单元或重派| L
L -->|候选 fingerprint| V["阶段 3 验证者 general(新鲜):尝试反证"]
V -->|confirmed / needs_validation / rejected| F["阶段 4 findings.json + report-schema.json"]
F --> V2["阶段 5 终稿验证者 research:verified / replace"]
V2 --> F
F --> R["阶段 6 REPORT.md / FINDINGS-DETAIL.md / NEEDS-VALIDATION.md"]
S["OS 沙箱:无外网 / 空环境 / 只读目标 / 资源限额"] -.-> H
S -.-> V
VAL["validate-*.cjs 零依赖校验器"] -.-> L
VAL -.-> F
阶段 1 侦察的四个 research 子智能体分别回答四个问题:产品是什么、谁有什么权限、外部输入从哪里进来流向哪里、本地平台能否满足沙箱要求。Parent 把结果综合成约 1,000 词上限的 architecture.md,并据此播种覆盖账本。阶段 2 覆盖驱动猎取按账本单元派出猎手,每轮结束后由一个新鲜的「覆盖评论员」挑漏,直到最终清场评论员也找不出遗漏。阶段 3 候选验证把每个候选交给没有参与猎取的验证者反证。阶段 4 结构化输出写入 findings.json 并过 Schema 与校验器。阶段 5 独立复核再派一批新鲜 research 智能体逐条核对终稿。阶段 6 目标中立报告从终稿记录派生三份 Markdown,且明文规定「散文不得改变任何裁决、严重度或阻塞项」。
4.2 核心机制一:确定性覆盖账本
传统 LLM 审计最大的黑箱是「它到底看了哪些地方」。这个技能用 coverage-ledger.json 把覆盖变成可枚举、可校验、可跨运行比对的数据结构。每个覆盖单元是「入口面 × 信任边界 × 子系统 × 攻击类」的一个组合,coverage_id 的生成规则刻意拒绝「有损 slug」:引用先归一为 Unicode NFC,再对 UTF-8 字节做 RFC 3986 百分号编码,最后用 :: 拼接。这样同一个源码对象在不同运行里永远得到同一个 ID;一旦出现重复 ID 而语义字段不同,校验器直接判定为「规范身份冲突」而不是静默合并。
每个单元只能处于七种状态之一,状态与字段间有严格不变量:planned 无负责人无证据,covered 必须有非空路径与检查记录且无未决项,candidate 是唯一允许挂指纹的状态,blocked 必须有部分证据和非空阻塞原因。被评论员重开的单元不覆盖旧证据,而是把旧的波次、负责人、证据追加进只增不删的 attempts 归档,新猎手从空证据起步——保证「第二次看」不被「第一次的结论」锚定。
{
"coverage_id": "src%2Frouter.ts%23POST%20%2Fusers%2F%3Aid::src%2Fauthz.ts%23requireOwner::packages%2Fapi::ATTACK-CLASSES.md%23Access%20control",
"canonical_refs": {
"surface": "src/router.ts#POST /users/:id",
"boundary": "src/authz.ts#requireOwner",
"subsystem": "packages/api",
"attack_class": "ATTACK-CLASSES.md#Access control"
},
"status": "candidate",
"wave": 2,
"agent_id": "hunter-authz-07",
"reviewed_paths": ["src/router.ts", "src/authz.ts"],
"local_checks": [{ "agent_id": "hunter-authz-07", "method": "source", "artifact": null, "invariant": "requireOwner 在 batch 路径同样生效", "result": "batch 分支绕过了 requireOwner" }],
"result_fingerprints": ["authz/users-batch-missing-owner-check"],
"attempts": [{ "wave": 1, "status": "blocked", "agent_id": "hunter-authz-03", "reassignment_reason": "未读 batch 分支" }]
}
账本还是预算的计量单位:一个单元约等于一次猎手调用,一个存活候选约等于一到两次验证者调用。用户给定「最多 N 次智能体调用」后,Parent 必须按「侦察 → 评论员 → 验证储备(约为余额的 30%)→ 猎手」的顺序预留,预算不够支付侦察和储备就一个智能体都不派,并写入 incomplete_reason。先付验证费、再花猎取费,杜绝「钱花光了只剩一堆没验证的候选被包装成发现」。
4.3 核心机制二:三元裁决与对抗式验证
findings.json 的 Schema 只允许三种记录,用 oneOf 分支加 additionalProperties: false 互斥:confirmed 必须带完整的 root_cause、intended_behavior、从 entrypoint 经 propagation 到 sink 的有序 trace、conditions、目标中立的 execution(含 payloads、instructions、非空 observed_result)、remediation、三维 severity(likelihood、impact、overall_severity)和 confidence;needs_validation 用 claimed_root_cause、非空 blockers 与至少一项 validation_plan,禁止携带严重度;rejected 只保留 claimed_root_cause、trace、evidence 和 reason,目的是让下次运行不再重复同一个被推翻的猜想。贯穿三态的是 fingerprint——一个源码派生、不含行号、不含波次、不含智能体名的稳定标识,正则 ^[A-Za-z0-9][A-Za-z0-9._:/@+-]*$。
验证的对抗性写在提示词第一句:「You did not write this candidate. Try to refute it from repository source and bounded local evidence.」验证者拿不到其他验证者的结论,必须重读每一处被引用的源码位置,能安全复现的决定性检查必须自己重跑。它可以把 needs_validation 提升为 confirmed,前提是独立建立了完整路径和有界观察结果;也可以把提议的 confirmed 降级,只要有一个部署或运行时事实在本地不可观察。阶段 5 更进一步:任何推向更强裁决、或实质改变根因、路径、影响、严重度的替换,都要再交给一个「没猎取、没验证、没提出这次替换」的第四方验证者重核;预算或独立性不足时,宁可把争议记录从 findings.json 里删掉、留在账本里标为未决候选。
严重度被刻意从「确定性」中剥离。SKILL.md 给了五档锚点:未认证者获得代码执行、完整数据存储访问或任意账户接管才是 critical;完全击穿一个显式安全控制(认证绕过、跨租户读写)是 high;真实边界违规但爆炸半径有限是 medium。判据只有一句:「如果你说不出具体损害,严重度就比感觉上的低。」
4.4 核心机制三:沙箱边界与写隔离
技能对执行目标代码的要求近乎苛刻:必须在 OS 强制的沙箱里,无外部网络、从空环境按显式允许列表填充变量、目标与工具链只读、目标进程只能写自己的 scratch/,并有明确的 CPU、内存、进程数、文件大小、磁盘、墙钟限额。任何一项做不到就不执行,候选停在 needs_validation 并写明缺的是哪项沙箱能力——这也是 HN 上「为什么要求 OS 级沙箱」一问的答案:技能会跑目标的构建、测试、模糊测试器,没有沙箱就不碰它们。
更精细的是「产物提升」程序。沙箱里产生的证据文件被视为「目标控制的内容」,只能由可信的 Parent 侧代码按 11 步流程搬进保留的 artifacts/:校验相对路径(拒绝绝对路径、..、符号链接组件),用提前打开的目录描述符做 no-follow 逐级遍历,以 fstat 核对是常规文件、硬链接数恰为 1 且不超预声明字节上限,拷贝后再 fstat 一次拒绝任何身份变化,目标侧独占创建。这段程序以逐字相同的围栏块嵌进猎手和验证者提示词,本质上是一份防 TOCTOU 的安全文件拷贝规范——作者假设的威胁模型里,被审计的仓库本身可能是恶意的。
4.5 性能取舍:profile、prompt 体积与「技能」形态的天花板
技能提供 quick、standard、deep 三档 profile:quick 粗化账本单元、只跑一轮猎手加一次最终评论员、两次验证合并为一次;deep 按子系统和生命周期细分单元、评论员跑到清场为止、两批验证独立进行。文档反复强调「profile 改变广度和冗余,从不改变证据门槛」。
代价是 token。HN 评论里有人在「相对小的 FastAPI 项目」上烧掉至少 15 万 token 并触发会话上限,另一位在中等代码库上「扔进去 100 万 token 一无所获」;更尖锐的批评指向设计本身——每个猎手提示词都要逐字包含 architecture.md、选中的攻击类块、核心方法、提升程序、验证规则和 Schema 分支,「把 14 份完整 Schema 塞进提示词是偷懒的设计」。作者的取舍在 PR #12 里说得明白:明确的停止条件与终态、深度有界探索、带字面返回信封的 Schema 分支,全部是为了换取子智能体输出的机器可解析性。换言之,它用上下文体积买确定性。
这也正是 Cloudflare 自己放弃「技能形态」的原因。博客列出了三道墙:上下文耗尽、崩溃后持久化缺失、单仓库会话看不见跨仓库接口。他们的解法是把 LLM 当作无状态计算引擎,状态全部外置到以 (run_id, repo, stage) 为键的 SQLite,每个智能体的上下文控制在窗口的 25% 以下。被外置状态取代的技能阶段几乎一一映射到平台的八个阶段:Recon、Hunt、Validate、Gapfill、Dedup、Trace、Feedback、Report。
4.6 与同类路线的差异
Semgrep 在 7 月的横评里把开源 AI 代码安全工具分成三派:LLM 主导的漏洞利用生成(如 Anthropic 已停维护的 defending-code-reference-harness,让智能体构造输入在 AddressSanitizer 下复现崩溃)、LLM 技能增强(本项目、Trail of Bits skills、Capital One vulnhunter、Google mantis)、SAST 与 LLM 混合(Vercel deepsec 的 198 条正则预筛、gadievron/raptor 的 Semgrep + CodeQL + AFL++ + Z3 全家桶、Cisco ai-deep-sast 的证据门)。本项目的独特位置在于:它是技能派里唯一把「覆盖」和「裁决」做成机器可校验契约的,又比混合派更彻底地相信模型——Cloudflare 博客甚至提到,在一个月的平台运行里 Semgrep 被调用了零次,而智能体自发写入的「Wishlist」(我想要但没有的工具或信息)被写了 25,472 次,是最常用的工具。
五、应用场景

5.1 场景一:接手遗留仓库或发版前的全量审计
痛点:接手一个几万行的遗留仓库,人工审计按人天计价,传统 SAST 扫出几百条告警却分不清轻重;发版前想要一份「哪些边界真的会被打穿」的清单。解决:装好技能后一句自然语言触发完整审计,产物落在 ~/security-audit-skill/<仓库名>/run-<N>/,其中 REPORT.md 按「先修哪个」排序,每条发现都带源码路径、复现步骤和最小修复。最小示例:
security audit this codebase
收益与量化:参考 Cloudflare 平台数据,约 30k 行代码的目标 3-4 小时产出约 100 条候选,压缩后约 80 个独立缺陷;确认记录全部带「有界本地复现」。适用边界:token 消耗与仓库规模成正比,HN 上小型项目也有 15 万 token 的实测;不确定时先说 do a quick audit 用 quick 档探路,再对高危子系统跑 deep。
5.2 场景二:把 scoped 审计嵌进 CI 门禁
痛点:每个 PR 都跑全量审计在成本上不现实。解决:scoped 运行只审「命名路径、单个子系统或两个源码引用之间的 diff」,账本只为范围内入口面播种,范围外显式记为 out_of_scope 而非假装覆盖。最小示例:
audit only the diff between v1.4.0 and HEAD, output to ~/audits/pr-482
收益:预算门控让花费可预估——「最多 N 次智能体调用」写进 run-metadata.json,验证储备先扣,超支时宁可 run_status: "incomplete" 也不虚报。边界:scoped 与 quick 运行必须在报告里自陈「部分覆盖」,不能当全量体检结论用;同一 PR 反复推送时,指纹机制会把上次被推翻的猜想标记为 rejected,避免重复劳动。
5.3 场景三:审计 LLM 应用与 MCP 服务器
痛点:智能体应用的信任边界长在数据流里——检索内容进上下文、模型输出进工具调用、MCP 响应进会话状态——传统 SAST 和通用审计提示都看不清这类漏洞。解决:AI-AND-LLM.md 把这个领域拆成 14 个攻击类,从间接注入、上下文串扰、持久记忆投毒,到工具参数注入、混淆代理、动作确认绑定、MCP 身份混淆,并给出反向判据:「提示注入本身不是发现」,必须有代码级边界失守——内容进了别人的上下文、调用了请求者不具备的权限、或驱动了别人够不着的汇点。最小示例:
security audit this repo, focus on the MCP server and agent tool dispatch
收益:发现以结构化记录落盘,例如「工具处理器未校验请求主体对目标资源的权限」会带完整 trace 与沙箱内复现,可直接转成工单;「守卫提示词不算安全边界」这条纪律能拦住大量自欺式修复。边界:供应商行为、部署路由、外部服务器身份在源码里不可见,这类候选会大量停在 needs_validation,需按 validation_plan 请运维方观察确认。
5.4 场景四:多轮增量运行与自建漏洞猎取平台的起点
痛点:一次运行永远不完整;安全团队想把技能升级成持续运行的平台。解决:技能的多次运行是累加的——Parent 读取所有历史账本与 findings.json,源码未变的 confirmed 记录按指纹携带进本轮(仍要过当轮验证),源码变了就生成重验单元,历史的 deferred、blocked、needs_validation 全部转成当前工作而不被旧结论压制。README 明说:单次运行大约只找到重复运行总发现的一半。收益:覆盖随轮次累积,是预算有限时最划算的用法;想走 Cloudflare 的路,博客把从技能到 VDH/VVS 平台的六周改造路径和外置状态设计都写清楚了。边界:平台化需要自建沙箱舰队、SQLite 状态层与修复流水线,Fixer 是其中最年轻、最慢的部件(每个缺陷约 5 分钟,发现到 PR 约 14 小时)。
六、快速上手
前置:一个支持工具调用与并行子智能体的编码智能体(Claude Code、Codex 等)、Node.js、可用的 OS 级沙箱(没有沙箱时审计仍可运行,但涉及执行目标代码的检查会停在待验证)。安装:
npx skills add https://github.com/cloudflare/security-audit-skill --skill security-audit
加 --global 装到用户级。然后在与目标仓库相关的会话里直接说 security audit this codebase;只问安全问题则进入引导模式,不会创建任何文件。产物目录默认在仓库外,人工产物校验可手动执行:
node <技能目录>/validate-findings.cjs <输出目录>/findings.json
node <技能目录>/validate-coverage-ledger.cjs <输出目录>/coverage-ledger.json
七、横向对比
| 项目 | 形态 | 路线 | 星数(2026-10-21) | 是否执行代码 | 产物形态 |
|---|---|---|---|---|---|
| security-audit-skill | 编码智能体技能 | 多智能体编排 + 对抗验证 | 33,494 | 沙箱内执行 | findings.json + 三份报告 |
| claude-code-security-review(Anthropic) | GitHub Action | PR diff 审查 + 误报过滤 | 6,458 | 不执行 | PR 行内评论 |
| deepsec(Vercel Labs) | 独立 harness | 198 条正则预筛 + AI 复核 | 8,223 | 不执行 | 发现列表(官方称误报降约 50%) |
| raptor(gadievron) | Claude Code 上的 Python 平台 | SAST + LLM 混合(Semgrep、CodeQL、AFL++、Z3) | 3,925 | 执行 + PoC + 补丁 | 漏洞报告与补丁 |
| trailofbits/skills | 技能合集 | 约 40 个安全技能,含 Semgrep/CodeQL 包装 | 7,664 | 视技能而定 | SARIF |
同样把智能体对准代码安全,Anthropic 的官方 Action 走的是「轻量、进 CI、只看 diff」路线,且 README 自陈「未针对提示注入加固,只应用于受信任的 PR」;本技能反其道而行——重编排、重证据、假设目标本身不可信。Semgrep 横评的结论是三条路线没有公认赢家:技能派适合已在用 Claude Code/Codex 的团队,平台派适合要无人值守流水线的安全团队。
八、局限与风险
token 成本是最大短板。15 万到 100 万 token 的社区实测意味着全量审计对个人开发者不友好,评论员循环和逐字嵌入的提示词块加剧了这一点;Synthesia 等团队已公开自建精简版配方。没有召回承诺:官方明确不声明漏报率,单次运行只覆盖重复运行总发现的一半,「清场」只是评论员视角的清场。强依赖沙箱能力:macOS 上没有开箱即用的等价物,缺沙箱会让执行类检查大面积停摆。模型拒答风险:HN 上有安全从业者反馈,「安全研究」框架会触发部分顶级模型的拒答,workaround 是按漏洞类拆分技能、去掉安全叙事。工程节奏偏慢:仓库无 release、无 tag,最后提交停在 2026-09-14,平台兼容问题主要靠文档纪律兜底。定位是防御:它教智能体的是「证明边界失守并给出最小修复」,不产出武器化内容,产物也不改动目标源码;但方法论本身是中性的,组织应对其使用范围负责。
九、小结与行动建议
这个项目值得关注的不是「又一个 AI 扫描器」,而是它把提示工程推到了工程契约的高度:覆盖可枚举、裁决可校验、验证可对抗、预算可核算。行动建议:第一,团队已在用 Claude Code 或 Codex 的,先对一个中等仓库跑 quick 档,把 REPORT.md 与 NEEDS-VALIDATION.md 的质量与现有 SAST 对比;第二,做智能体产品的,精读 AI-AND-LLM.md,它就是一份免费的 LLM 应用威胁建模清单;第三,计划自建安全平台的,把 Cloudflare 博客和 PR #12 当设计文档读,外置状态与验证前置两条经验可直接复用;第四,把它当「审计方法论的开源实现」而非「免费产品」,预算和沙箱要先备好;第五,跟进仓库动态,社区已在催 token 优化。
参考资料
- cloudflare/security-audit-skill 仓库(获取日期 2026-10-21,星数、提交与文档内容均以此为准)
- Build your own vulnerability harness — Cloudflare Blog(2026-06-18,Grant Bourzikas,平台数据来源)
- PR #12:Rework the audit workflow, findings contract, and validators end to end(2026-09-10 合入,v2 重构说明与验证记录)
- Hacker News:Cloudflare/Security-Audit-Skill 讨论(2026-09-17,213 分,token 成本与模型拒答实测)
- Comparing Open-Source AI Code Security Harnesses — Semgrep Blog(2026-07-20,三路线横评框架)
- anthropics/claude-code-security-review(获取日期 2026-10-21,对比项数据)
读者留言
COMMENTS 暂无还没有留言,来说第一句?