Cloudflare Security Audit Skill 怎么用:先看它如何验证发现

让 AI 扫描代码并列出漏洞,得到一长串“高危”并不难。难的是逐条回答:哪一段输入能到达危险操作,在哪些前提下真的发生,是否已经被校验拦住?Cloudflare 的 security-audit-skill 值得注意,恰在于它把“发现了什么”与“证实了什么”分开记录,而没有把一次模型判断直接写成最终结论。

如果在找 Claude Code 的普通插件或 Hook 防护,另见 Claude Code Mods 的安装与权限检查;一个等待用户确认危险命令的 Hook,并不等于一次覆盖源码与运行行为的安全审计。

代码安全审计与独立验证的概念插画(AI 生成)

#从技能入口到审计记录

项目 README 给出的项目级安装命令如下;若需用户级安装,再按仓库说明添加 --global。npx skills 是技能安装工具,不是 Cloudflare 自行发布的一款扫描器,运行前应确认所用的 Agent 支持该技能,并阅读安装过程拟写入的文件。

1
npx skills add https://github.com/cloudflare/security-audit-skill --skill security-audit

安装后在目标仓库中请求 security audit this codebase,或指定 find security vulnerabilities in ./src。完整代码库审计与针对某个安全问题的咨询,触发的工作模式可能不同;需要报告文件时,应明确指定输出路径。官方说明称,未指定时完整审计默认写到用户目录下的 ~/security-audit-skill/<repo-name>/run-<N>;只有显式选了仓库内且被版本控制忽略的目录,才会把结果写入目标仓库。含敏感细节的审计文件不宜顺手加入 Git。

它的工作流程分成六个阶段:先摸清架构、信任边界与输入面,形成 architecture.md 和 coverage-ledger.json;再按覆盖单元派发检查,收集候选漏洞;随后把每个候选交给独立的验证者尝试证伪,并写入结构化的 findings.json;最终的记录再由独立 Agent 复核,报告从经过核对的记录生成。这里最值得学的是证据链:报告中的一句“存在漏洞”,须能回到源代码、可达路径和可观察结果。

#三类结果不能混读

官方把发现分为 confirmed、needs_validation 和 rejected。前者要求完整的源码追踪和有界的观察结果;第二类须写出尚未确定的具体事实,而且不标严重程度;第三类保存被推翻的候选。它还附带 validate-findings.cjs 与 validate-coverage-ledger.cjs 等校验器,用于检查输出结构与覆盖账本。结构校验能防止字段缺失,却不会凭空证明业务权限判断正确;独立验证也不能保证已经穷尽所有攻击路径。

#先定义审计范围,再看报告

假设是一套有登录、文件上传和管理员后台的 Web 服务。交给 Agent 的任务不能只写“找漏洞”,还应说明代码版本、哪些目录属于服务端、身份认证在哪里、测试环境是否可用,以及它可以触及哪些数据。读 architecture.md 时,首先看它是否识别出匿名请求与登录请求的边界、普通用户与管理员的边界、文件上传后保存与读取的路径;读 coverage-ledger.json 时再问:这些入口中有哪一个被覆盖,哪一个仍未检查,哪些结论沿用了上次运行的证据?官方在 工作流程说明 中把账本校验放在勘察阶段及每次更新之后,就是为了使“没查过”不被写成“查过且没问题”。

要演示验证思路,可以设计一个自己授权的玩具项目:用户上传文件时,服务器把用户给出的名字拼进目标路径,但在落盘之前还有一层路径规范化与根目录校验。单看拼接代码会怀疑目录穿越;若后面的校验确实拦住逃逸,它就不应作为 confirmed 漏洞。反过来,若校验只检查字符串里是否含 ..,而另一个入口在解码后才拼路径,也许存在可达的绕过条件。该条件仍须用代码追踪和隔离环境中的授权测试证实。这里是教学假设,不是对任何真实仓库的发现。

findings.json 的 仓库 schema 为三种判定规定了不同字段。confirmed 需填写 root_cause、intended_behavior、trace、evidence、conditions、execution、remediation、severity 和 confidence 等;needs_validation 则记录 claimed_root_cause、blockers 与 validation_plan,并不要求 severity;rejected 需说明 reason。这不是为报告凑字段,而是逼着审计者说出“哪一段代码造成问题”“在哪些条件下可观察到”“还卡在哪个事实”。没有源码定位和边界条件的高危标题,只能算待办线索。

#运行限制会改变结论

Cloudflare 的 运行要求 包括支持工具调用与并行子 Agent 的模型、Node.js,以及对目标代码的构建、测试、进程、浏览器等活动提供操作系统强制隔离:关闭外网、环境变量白名单、资源限制、仅允许指定暂存路径写入。少了这些控制,技能设计要求保留为 needs_validation,不能为证明漏洞而贸然运行目标控制的代码。容器、VM 或沙盒也应先核对网络与挂载配置,单凭“在测试仓库里”并不能算隔离。

报告完成后我会按一个顺序复核:先看 REPORT.md 的每个结论能否在 FINDINGS-DETAIL.md 和 findings.json 找到同一条记录,再看记录的 trace 是否指向本次代码版本,最后检查 NEEDS-VALIDATION.md 是否列出了具体下一步而非模糊的“待进一步调查”。validate-findings.cjs 和 validate-coverage-ledger.cjs 的作用是检查结构及约束,并不能替人判断权限设计是否符合业务,也不会保证所有入口都找到了。官方 验证与报告阶段 把这些边界写得颇清楚。

常见问题是“为什么跑了审计,却只收到 needs_validation”。原因未必是技能无能:目标项目的测试可能需要生产凭证、外部网络或数据库副本,而这些条件不该为了让结果更漂亮就放宽;也可能是输入路径没有证明可达,或校验流程中仍存在一个未解决的分支。应把 blockers 和 validation_plan 读成一份具体的后续工作清单,在隔离且授权的环境逐项核对,而不能直接将它改标为 confirmed。相反,报告里某个候选被证伪,也不表示整类漏洞在其他入口不存在,只说明这条候选的证据不足。

审计涉及外部代码时,另一项实务问题是报告本身可能泄露敏感内容:路径、内部接口、令牌形态与漏洞条件往往都记录得很细。输出目录最好与源仓库分开,并控制分享范围;贴进公开 issue 前,先去掉凭证和能直接用于攻击真实服务的细节。这里没有一种“一键跑完便合格”的定义,只有覆盖范围和证据质量能决定报告值不值得信。

实际使用时,我会先选一个自己有权限审计的小项目,明确范围,检查生成的覆盖账本是否遗漏入口,然后抽查一条 confirmed 的源码路径、一条 needs_validation 的未决条件,以及一条 rejected 的反证。本文依据项目 README 整理安装与流程,没有在本站仓库实际执行一次安全审计,也没有声称查出任何漏洞。代码审计最容易出现的错觉,是把漂亮的报告当成可靠的证据;至于证据够不够,仍得由审计目标和读报告的人来检验。

资料:Cloudflare security-audit-skill 仓库及 README