引言
"A coding-agent skill for multi-phase security audits with independently verified, machine-readable findings."
这是「每日一个开源项目」系列的第 222 篇 。今天的项目是 security-audit ------ Cloudflare 出品的 coding-agent skill,13,825 颗 Star,MIT 许可证。
security-audit 解决一个关键问题:怎样让 AI Agent 做的安全审计,结果可信到能交给安全团队审阅? 答案不是"让模型更聪明",而是用一套结构化的流程------六阶段审计、对抗性验证、机器可读的发现记录------把"模型说这里有问题"变成"这里有源码证据、有可复现路径、有优先级排序的确认漏洞"。
你会学到什么
- 六阶段安全审计流程:从侦察到目标中立报告
- 对抗性验证的设计原则(检查者永远不是发现者)
- 三种 verdict 的区别:
confirmed/needs_validation/rejected - 覆盖率账本(coverage-ledger)如何让多轮审计结果可累加
- 沙箱要求:为什么"不能执行目标代码"时只能标
needs_validation
前提知识
- 使用过 Claude Code 或类似 coding agent 和 skill 机制
- 了解基本的安全审计概念(攻击面、信任边界、漏洞确认)
- Node.js 基础使用经验
项目背景
概述
这个 skill 是 Cloudflare 漏洞发现 harness 的单仓库起点 。Cloudflare 在官方博客 Build your own vulnerability harness 里描述了这套系统如何演进成多阶段、覆盖整个 fleet 的漏洞发现平台,而 security-audit 就是它最早的单仓库版本。
它不是"生成一个安全报告"的 prompt 模板,而是一个编排系统:用隔离的子 Agent 跑侦察、狩猎、验证、核实,每一步的产出都有结构化的记录和独立的校验器。
项目信息
- 组织: Cloudflare
- 主要语言: JavaScript(校验器零依赖,用 Node.js 写)
- 许可证: MIT
- 创建时间: 2026-06-18
项目数据
- ⭐ GitHub Stars: 13,825+
- 🍴 Forks: 740+
- 📄 许可证: MIT
- 📅 创建时间: 2026-06-18
快速上手
安装
bash
# 用 Skills CLI 安装
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
使用
启动你的 coding agent,指向要审计的代码库,然后说:
kotlin
security audit this codebase
或者:
arduino
find security vulnerabilities in ./src
javascript
do a security review, output to ~/audits/my-project
当请求匹配触发词(security audit / find vulnerabilities / pen-test 等)时,skill 自动激活。
两种模式
| 模式 | 触发条件 | 行为 |
|---|---|---|
| guidance | 安全问题、聚焦审查、方法论咨询 | 只使用相关部分,不跑全流程,不写文件 |
| full audit | 明确要求审计/渗透测试、端到端审查 | 跑完整六阶段,写报告文件 |
核心:六阶段审计流程
Phase 1:侦察(Reconnaissance)
并行启动多个 research Agent,每个返回结构化的源码事实(带 file:line 引用):
- Agent 1a:产品类型、技术栈、构建命令、子系统边界
- Agent 1b:主体(principal)、权限、信任边界、控制点
- Agent 1c:入口面、副本、sink(数据汇点)
产出 architecture.md(架构图)和 coverage-ledger.json(覆盖率账本)。侦察阶段只读,不接触外部服务。
Phase 2:覆盖率导向的漏洞狩猎
根据账本把"覆盖率单元"分配给隔离的 general Agent。每个 hunter 只读自己负责的源码块,只写自己的 scratch/ 目录,返回一个结构化结果。
关键:coverage critic 会找出狩猎覆盖的缺口------哪些单元被漏掉了、哪些分配有重叠。
Phase 3:候选独立验证
每个唯一候选(去重后)交给一个全新的、没有狩猎过它的 verifier,试图证伪它。
验证器的 prompt 明确说:"你没有写这个候选,尝试从源码和有边界的本地证据反驳它。"
Phase 4:结构化输出
写出三种 verdict 的记录到 findings.json,并用 validate-findings.cjs 校验。
Phase 5:独立记录核实
全新的 Agent 核实最终源码声明。如果有实质性替换,替换后的内容再交给另一个独立 verifier。
Phase 6:目标中立报告
从已验证的记录和覆盖率账本,派生出 REPORT.md、FINDINGS-DETAIL.md、NEEDS-VALIDATION.md。
三种 Verdict:语义清晰
这是 security-audit 设计上最值得学习的地方------verdict 不是"高中低风险",而是"证据完整度":
| Verdict | 含义 |
|---|---|
confirmed |
有完整的源码 trace,有有界可复现的观察结果 |
needs_validation |
有一个精确的未解决事实,但没有标注严重度 |
rejected |
一个被证伪的候选(记录了为什么否定它) |
关键原则:"有一个源码证据支撑的疑点" ≠ "确认漏洞" 。当一个 lead 因为沙箱限制无法执行验证时,它保持 needs_validation,而不是被草率地标成 confirmed 或丢弃。
设计原则
1. 对抗性验证
检查发现的那个 Agent,永远不是发现它的那个 Agent。这防止了模型"自我确认"------它自己发现的问题,自己又验证一遍,往往会倾向于确认。
2. 严重度需要影响
严重度 = 可能性 × 影响,而不是"偏离了 checklist 多少"。一个符合清单但无实际影响的问题,不是漏洞。
3. 纵深防御缺口不是漏洞
如果 Layer A 已经阻止了攻击,Layer B 的缺失只是一个加固建议(hardening note),不是漏洞。
4. 多轮运行提升覆盖率
Cloudflare 的实测:单轮运行找到的漏洞,大约只有多轮运行累计找到的一半。所以 skill 设计成"对同一仓库的多次运行是可累加的"------每轮用上一轮的账本和发现来定位缺口。
覆盖率账本:让审计可累加
coverage-ledger.json 是这个 skill 的核心数据资产。
普通的安全审计是一次性的------跑一遍,出一份报告,下次再跑等于从零开始。security-audit 的账本让审计可增量:
arduino
第一轮审计:
→ 生成 coverage-ledger.json(记录哪些单元已覆盖、哪些确认、哪些存疑)
→ 找到 N 个漏洞
第二轮审计(同一仓库):
→ 读取上一轮的账本和 findings
→ 只针对"未覆盖的缺口"和"变更的源码"重新狩猎
→ 把"当前源码仍有证据支撑"的旧发现携带过来
→ 不把"过时或未解决的旧发现"当作已覆盖
每个单元有状态:planned(计划)→ in_progress(进行中)→ completed(完成)/ deferred(因预算推迟)。如果一个单元因为 agent 数量限制无法分配,它被显式标记为 deferred,而不是被静默丢弃。
机器可读的发现记录
findings.json 遵循 report-schema.json 定义的 schema,配合零依赖的校验器:
| 文件 | 作用 |
|---|---|
report-schema.json |
三种 verdict 的 JSON schema |
validate-findings.cjs |
零依赖校验器(Phase 4/5 用) |
validate-coverage-ledger.cjs |
覆盖率账本校验器(Phase 1-5 用) |
父 Agent 在创建账本后、每次更新账本后都会跑 validate-coverage-ledger.cjs;在 Phase 4 和每次 Phase 5 替换后跑 validate-findings.cjs。
这个"机器可读 + 独立校验"的设计,让审计产出可以接入下游工具链,而不是一份只能人看的 PDF。
沙箱要求:一个诚实的边界
security-audit 明确要求:执行目标控制的代码,必须在 OS 强制的沙箱里。
沙箱必须:
- 禁止外部网络
- 使用净化的 allowlist 环境
- 强制资源限制
- 只允许写入指定的 scratch 路径
如果这些控制不可用,工作流不执行目标代码 ,把 lead 保持为 needs_validation。
这是一个很诚实的工程决策:宁可不确认,也不在没有安全边界的情况下运行可能恶意的代码。在 AI 安全审计工具里,这种对"验证边界"的明确态度,比"我能自动跑 PoC"更值得信任。
参考资源
- 🌟 GitHub : cloudflare/security-audit-skill
- 📝 背景博客 : Build your own vulnerability harness
- 🔧 Skills CLI : skills.sh
- ✉️ 联系 : security-ai-research@cloudflare.com
总结
security-audit 代表了一个判断:AI 安全审计的瓶颈不在"模型能不能发现漏洞",而在"发现的结果能不能被信任"。
三点值得注意:
对抗性验证是可信度的核心。 很多 AI 审计工具的问题,是发现和验证由同一个模型完成------模型找到的"漏洞",模型自己再验证一遍,天然有确认偏差。security-audit 用"检查者≠发现者"的结构化约束,把这种偏差从流程层面切掉。
Verdict 语义 = 证据完整度,不是风险等级。 confirmed / needs_validation / rejected 三个状态描述的是"证据链到哪一步断了",而不是"这个问题多严重"。严重度(可能性×影响)是 confirmed 内部的一个字段。这种分离让审计结果可以被机器处理,也能被安全团队信任。
覆盖率的可累加性解决了"审计是一次性的"这个老问题。 传统安全审计做完就过时了。security-audit 的覆盖率账本让审计变成可增量的:每次跑都建立在之前的覆盖基础上,只补缺口、只重验变更。这更接近"持续安全"而非"周期性审计"。
如果你在用 coding agent 做安全相关工作,或者想理解如何让 AI 产出的安全结论变得可信,security-audit 是目前最完整的开源参考。
探索 PrimeSkills ------ 精选 AI agent 和技能工具,每一个都经过真实工作流验证。没有炒作,只有真正好用的工具。
访问我的个人主页,获取更多见解和有趣的产品。