Security Audit:安全审计官(2)
上一部分我们拆开了 Cloudflare 的 security-audit-skill:它是一个给编码 agent 用的 skill,源自 Cloudflare 漏洞发现 harness 的"单仓库起点";它把审计切成侦察、覆盖率驱动的挖掘、候选验证、结构化输出、独立记录核验、报告六个阶段,坚持"找洞的人和验洞的人不是同一个",并用 confirmed、needs_validation、rejected 三种裁决把结论说清楚。
道理讲完了,这一部分聊点实在的:怎么装,怎么用,跑起来之前要准备什么,以及我对它的几点看法。先说一句:README 写得很克制,很多你可能关心的数字(耗时、成本、检出率)它都没给。凡是它没说的,我会老实写"README 未说明",不替它脑补。
一、安装:一条 npx 命令
装它的过程简单到有点不真实。README 推荐用 Skills CLI:
npx skills add cloudflare/security-audit-skill \
--skill security-audit
这条命令的意思很直白:从这个 GitHub 仓库里,把名叫 security-audit 的 skill 装进你的编码 agent。如果你想让它在所有项目里都能用,而不是只在当前项目里,就加上 --global,做成用户级安装:
npx skills add cloudflare/security-audit-skill \
--skill security-audit \
--global
至于具体装给哪个 agent、怎么跳过交互式选择,README 只说了一句:运行 npx skills --help 查看 agent 选择和非交互选项。也就是说,它支持哪些 agent 的完整名单,README 未说明,你得自己看 CLI 的帮助。
回想一下第 1 部分讲过的:这个 skill 本质上是一堆写给 agent 看的 Markdown 说明书,加上几个小脚本。所以"安装"其实就是把这套说明书放到 agent 能读到的地方。没有服务要起,没有数据库要配,也没有账号要注册。这一点很讨人喜欢:试错成本低,不满意删掉就行。
二、怎么用:说一句话就启动
装好之后怎么用?README 的答案同样简单:在你想审计的代码库里启动编码 agent(或者让 agent 指向那个代码库),然后用大白话提要求。它给了三个例子:
security audit this codebase
find security vulnerabilities in ./src
do a security review, output to ~/audits/my-project
第一句是最朴素的版本,整个代码库都审;第二句把范围缩到 ./src;第三句顺便指定了输出目录。三句话你不需要记任何参数,也没有什么配置文件要写。
你可能会问:agent 怎么知道该启用这个 skill?README 说,skill 会在你的请求匹配触发条件时自动激活,触发词包括 security audit、find vulnerabilities、pen-test the code 等等。换句话说,你不必点名"请使用 security-audit",像跟同事说话那样提需求就行。我觉得这是 skill 这种形态很舒服的地方:能力藏在后面,需要时自己冒出来。
三、两种模式与输出目录
这里有一个容易被忽略、但我觉得很见功力的细节:同样是"安全相关"的话,skill 并不会每次都开足马力跑完六个阶段。
按 README 的说法,它分两种模式:
- 完整审计模式(full audit mode):当你直接要求审计代码库,或者要求做渗透测试(pen-test)时启用。这就是第 1 部分讲的整套流水线,产出 findings.json、REPORT.md、FINDINGS-DETAIL.md、NEEDS-VALIDATION.md 等文件。
- 指导模式(guidance mode):当你问的是安全问题,或者是针对性的漏洞工作时使用。除非你明确要求报告产物,否则它不会走完整流程。
我喜欢这个设计,因为它尊重你的意图。想象你只是问"这段代码的 JWT 校验有没有问题",结果 agent 突然拉起一支小队,开始写覆盖账本,这就有点杀鸡用牛刀了。分成两档,轻问题轻答,重任务重做,各取所需。
再说文件放哪。完整模式下,如果你没指定输出目录,默认写到:
~/security-audit-skill/<repo-name>/run-<N>
注意这是在你的 home 目录下,而不是目标仓库里;run-<N> 的编号则对应第几次运行,这和后面要说的"多次运行"正好呼应。README 还补了一条规矩:只有当你明确选择一个被版本控制忽略的目录时,工作流才会往目标仓库里写文件。
这条规矩很有安全工程师的味道。审计产物里有未公开的漏洞细节,要是一不小心被 git add . 提交上去,那就是自己给自己挖坑。默认放在仓库之外,要放进去也得是 gitignore 掉的目录,等于在你手滑之前先拦了一道。
四、运行前提:沙盒是硬要求
现在说一个你在动手之前必须知道的事。README 的"Requirements"一节列了三样东西:
- 一个编码 agent,背后的模型要支持工具调用和并行子 agent。回想第 1 部分,整个流程靠"隔离的 agent"分工,所以并行子 agent 不是锦上添花,而是骨架。
- Node.js。原因是前面提到的两个校验器 validate-findings.cjs 和 validate-coverage-ledger.cjs,它们是零依赖脚本,但得有 Node 才能跑。
- 一个由操作系统强制执行的沙盒。
第三条最值得多说几句。审计过程中,agent 可能需要构建目标项目、跑测试、启动进程、开浏览器、起模拟器、跑 fuzzer、加载各种 fixture。这些东西都是"目标控制的",也就是说,里面的代码是你正在审计的那个项目的,它可能有问题,甚至可能有恶意。
README 对这个沙盒提了四条具体要求:
- 必须禁用外部网络;
- 使用经过净化的、白名单式的环境变量;
- 强制执行资源限制;
- 只允许写入指定的 scratch 路径。
打个比方:这就像请人去检查一栋可疑的老房子,你得先让他穿好防护服、断掉外面的电话线、限制他能碰的范围,而不是让他带着你家钥匙和钱包直接进去。环境变量要净化,是因为里面常常有你的密钥;禁网络,是怕被审计的代码把东西往外送;限资源,是怕它把机器拖垮;限写入路径,是怕它改到不该改的东西。
那如果你没有这样的沙盒呢?README 的回答很干脆,也很诚实:没有这些控制,工作流会把对应的线索保持为 needs_validation,而不去执行目标代码。
这个取舍我觉得挺聪明。它没有假装"反正我小心点就行",而是承认:不能安全地执行,就不去执行,把结论如实降级为"还有一个事实没验证"。这和第 1 部分里 needs_validation 的定位完全一致:有源码依据、但被阻塞的线索,写明未解决的那个事实,不给严重程度。换句话说,沙盒决定的不是"能不能审计",而是"有多少线索能被推进成 confirmed"。没有沙盒,你仍然能得到报告,只是里面"待验证"的比例会更高。README 没有给出具体会多出多少,这一点 README 未说明。
五、设计原则与多次运行
README 用五条原则收尾,它们其实是前面所有机制背后的"价值观"。我按自己的理解串一遍。
只确认已成立的边界失效。 一条线索,哪怕源码里看着很可疑,但如果还卡着一个没法确认的事实,那就只能是 needs_validation,并且要写明"到底差哪个事实"。这让"确认"这个词保持了分量。
对抗式验证。 检查发现的 agent,永远不是做出发现的 agent。这是第 1 部分的重头戏,不再重复,只提一点:它是把"自己给自己打分"这个老毛病从流程上堵死。
严重度要看影响。 README 的写法是"可能性乘以影响",而不是"偏离清单"。意思是,别因为某处不符合某条最佳实践就喊严重;要看真有人利用的可能性有多大、后果有多重。
纵深防御的缺口不是漏洞。 README 举的例子很清楚:如果 A 层已经挡住了攻击,那么缺少 B 层只是一条加固提示。这条原则对读报告的人特别友好。你大概见过那种动辄几十页、把"缺少某个响应头"也当成问题的扫描报告,最后真正要紧的那两条被淹没了。这条原则就是在对抗这种噪音。
多次运行提高覆盖。 这一条是唯一带数字的。README 说,在 Cloudflare 自己的测试运行中,单次运行大约只发现了多次运行总共发现的漏洞的一半。
我想在这里停一下,因为这个数字很有意思,也需要小心解读。它的意思是:对同一个仓库反复跑,累计能发现的东西,大约是单次的两倍。这背后的道理不难理解:让 agent 去"找洞",本来就带有随机性,每次走的路径不一样,总有漏掉的地方。但要注意措辞:README 说的是"在我们的测试运行中",测试的是哪些目标、跑了多少次、怎么统计,README 未说明。所以别把它当成通用定律,更稳妥的读法是:官方自己的经验是,一次不够。
好在 skill 对"多次运行"是有准备的。README 说,对同一个仓库的多次运行是累加的:它会利用之前的覆盖账本和发现,去瞄准还没覆盖到的缺口,对已经变化的源码重新验证,把仍然有效的证据带到新一轮里。同时有一条红线:不会把过期的或未解决的工作当作"已覆盖"。
这其实就是第 1 部分说的"覆盖账本"在发挥作用。它让第二次、第三次运行不是从零开始瞎撞,而更像接力:上一棒跑到哪、哪些地方看过、哪些地方代码后来又改了,账本都记着。而默认输出目录里那个 run-<N> 的编号,也正好是这套累加机制的落脚点。
六、适合谁与局限评价
聊到这里,可以说说我的看法了。以下的"适合谁"是我基于 README 事实的推断,不是 README 的原话。
可能适合你,如果你:
- 已经在日常用编码 agent,而且这个 agent 支持工具调用和并行子 agent;
- 手里有想做一次系统性安全检查的代码库,希望拿到的是"有人验证过"的结果,而不是一份让人将信将疑的清单;
- 能提供一个符合要求的操作系统级沙盒,让 agent 放心地构建和运行目标代码;
- 在意报告的可读性:README 里提到的 findings.json 是按 report-schema.json 校验的机器可读记录,方便接进你自己的流程;同时还有面向人读的 REPORT.md 等文件。
需要留个心眼的地方:
- 沙盒门槛不低。 这是最现实的一条。没有符合要求的沙盒,很多线索只能停在 needs_validation。如果你期待"一键出结论",这一步可能得先花点功夫。
- 依赖 agent 的能力。 skill 本身是一套说明书,干活的是你的 agent 和背后的模型。README 只要求模型支持工具调用和并行子 agent,不同模型表现如何,README 未说明。
- 缺少公开的量化数据。 除了"单次约为多次的一半"这一句,README 没有给出检出率、误报率、耗时或成本。你想估算跑一次要花多少、能找到多少,只能自己试。
- 多次运行意味着多次投入。 既然官方说一次不够,那么要拿到更完整的覆盖,就得接受多跑几轮。每轮的开销,README 未说明。
- 它不替代人。 这是我的看法,不是 README 的话:needs_validation 这个裁决本身就在提醒你,有些事实还需要有人(或有环境)去确认。把它当成一个纪律严明的初级审计小队,会比当成"全自动保险"更合理。
再说一个我个人很欣赏的点:这个项目最动人的地方,其实不是"让 AI 找洞",而是它对"不确定"的态度。有依据但验证不了,就老实标成待验证;缺了第二层防护,就当加固建议而不是漏洞;过期的工作不算已覆盖。它在反复做同一件事:不让结论比证据走得更远。在一个人人都在炫耀"AI 找到了多少漏洞"的时代,这种克制反而很稀罕。
如果你想和作者交流,README 给了一个联系邮箱,欢迎讨论、反馈,或者交换 AI 驱动安全工具方面的心得。
本部分小结
- 安装只要一条 npx skills add … --skill security-audit,需要全局可用就加 --global。
- 使用方式是直接用自然语言提需求,如「security audit this codebase」;请求匹配触发词时 skill 自动激活。
- 直接要求审计或渗透测试走完整审计模式,安全问题和针对性漏洞工作默认走指导模式;完整模式默认输出到 ~/security-audit-skill/<repo-name>/run-<N>,只有你选了被版本控制忽略的目录才会写进目标仓库。
- 运行需要支持工具调用和并行子 agent 的编码 agent、Node.js,以及禁网络、净化环境变量、限资源、限写入路径的操作系统级沙盒;没有沙盒,线索会保持为 needs_validation,不会执行目标代码。
- 五条原则:只确认已成立的边界失效、对抗式验证、严重度看影响、纵深防御缺口不是漏洞、多次运行提高覆盖;官方测试中单次运行大约只发现多次运行总和的一半。
- 局限:沙盒门槛、依赖 agent 能力,以及 README 没有给出检出率、成本、耗时等数据。
项目信息
- 仓库:cloudflare/security-audit-skill
- 语言:JavaScript
- Star:仓库页显示 50.3k;热点站周报快照总 star 46,962,本周新增 15,072
- Fork:3.2k
- 许可证:MIT
- 点赞
- 收藏
- 关注作者
评论(0)