GitHub 今日推荐|security-audit-skill:让编码代理自己审计漏洞还互相验证

0 阅读1分钟

文章封面

一句话看懂

项目地址:github.com/cloudflare/… cover

security-audit-skill 是 Cloudflare 开源的一套技能文件,目的是让支持工具调用的编码代理按固定流程做安全审计,从梳理架构开始,到分头找漏洞、互相验证、最后生成报告。仓库主语言是 JavaScript,核心内容其实是 Markdown 说明文档加几个校验脚本,代码量不大,但流程设计得很细。README 里写得很直接,这就是 Cloudflare 内部漏洞发现系统的种子技能,内部那套更大的审计 harness 就是从这份公开技能演化出来的。

仓库当前 34342 星,当日新增 1865,fork 数 2148,关注度正在快速上升。license 是 MIT,open issue 有 72 个,项目创建于 2026 年 6 月,最近一次 push 在 9 月,更新还算活跃。

它解决什么问题

让 AI 代理做代码审计,最大的风险是它一本正经地报告一个不存在的漏洞,或者走马观花漏掉大半代码。这个项目要解决的就是这两件事:怎么让代理把代码库看全,怎么让代理说出来的结论靠得住。

它给出的办法是拆流程加互相校验。审计不是一个代理从头跑到尾,而是分成侦察、狩猎、验证、输出、再验证、报告六步,每一步都有明确的产出文件和下一步的输入要求。每个候选发现都要交给一个全新建立的代理去尝试反驳,不是原来找到问题的那个代理自己给自己背书。README 里还提到一个很实际的数据,单次运行平均只能找到多次累计运行发现漏洞总数的一半左右,所以项目把多轮运行也设计成累加模式,后续运行能利用前面留下的覆盖账本和发现记录,不用从零开始。

核心概念速览

coverage-ledger,中文可以理解成覆盖账本,记录这次审计到底看过代码库里的哪些单元,看到什么程度。在项目里它是一个叫 coverage-ledger.json 的文件,里面写明确定性的覆盖单元和每个单元的状态,后续运行靠这个文件知道哪里还没查过。

findings.json,存放审计发现结果的文件。项目要求这个文件只能写三类记录:confirmed(确认)、needs_validation(待验证)、rejected(已否定),而且格式必须符合 report-schema.json 定义的结构,写错字段校验脚本会直接报错。

isolated hunters,直译是孤立的猎手,指互不干扰、分头去找问题的多个代理实例。项目会从覆盖账本里给每个猎手分配一块没查过的单元,让它们各自去查,检查记录会被记下来,避免大家都盯着同一块代码重复劳动。

fresh verifier,全新的验证者。每当有一个候选发现产生,系统会启动一个全新的代理实例去尝试推翻它,而不是让原来的猎手自我检查。这个设计是整套流程里信任度的核心来源。

架构拆解

arch

整个技能库按阶段组织成几份 Markdown 文档和配套脚本。RECONNAISSANCE.md 负责第一阶段的侦察工作,产出 architecture.md,用来映射代码库的架构、信任边界、输入面和初步覆盖范围。这份架构文档生成之后,紧接着会触发 validate-coverage-ledger.cjs 做一次校验,确认覆盖账本结构没问题。

HUNTING.md 管第二阶段,负责编排多个孤立猎手去按覆盖账本分配的区域搜寻漏洞,这个文件里也写明了具体的狩猎方法和验证规则。每次覆盖账本更新之后,还会再跑一遍 validate-coverage-ledger.cjs,保证账本始终处于可信状态。

第三到第六阶段都写在 VALIDATION-AND-REPORTING.md 里,涵盖候选验证、结构化输出、独立记录验证、目标中立报告四个环节。候选验证阶段由全新验证者尝试反驳每条候选发现,通过的进入结构化输出,写进 findings.json。这一步完成后以及之后每次替换 findings.json 内容,都会触发 validate-findings.cjs,这个脚本依据 report-schema.json 里定义的 schema 做校验,确保三类 verdict 的字段格式始终一致。独立记录验证阶段再找一批新代理核实最终的来源声明是否站得住,最后一步才生成面向目标、保持中立措辞的 REPORT.md。

从这个结构能看出一条清晰的校验链路:架构文档触发账本校验,账本更新再触发账本校验,候选输出和每次替换都触发发现校验,发现校验又依赖 schema 定义。整条链路里每一步格式是否正确都由脚本硬卡,不靠人工肉眼确认。

关键实现走读

项目里公开的代码并不多,其中 validate-findings.cjs 里的 deepEqual 函数值得细看:

function deepEqual(left, right) {
  if (left === right) return true;
  if (typeOf(left) !== typeOf(right)) return false;
  if (Array.isArray(left)) {
    return left.length === right.length && left.every((value, index) => deepEqual(value, right[index]));
  }
  if (left !== null && typeof left === "object") {
    const leftKeys = Object.keys(left);
    const rightKeys = Object.keys(right);
    return leftKeys.length === rightKeys.length &&
      leftKeys.every((key) => hasOwn(right, key) && deepEqual(left[key], right[key]));
  }
  return false;
}

做了什么:这是一个手写的深度比较函数,逐层比较两个值是否结构和内容完全一致。先判断类型是否相同,再分别处理数组和对象的递归比较,数组按顺序逐项比对,对象先比键的数量再逐键递归比对,其余情况直接走值相等判断。

为什么这样写:README 提到这套验证器零依赖,不借助任何第三方库,全靠纯 JavaScript 实现。要校验 findings.json 里的记录是否符合 schema 定义的结构,免不了要做对象和数组的深度比较,社区里常见的做法是直接装一个 lodash 或类似的工具库,但那样会给这个本应轻量的技能脚本引入额外依赖和版本管理负担。手写一个几行的递归函数就能满足需求,脚本可以单独跑,不需要先装 node_modules。

没有它会怎样:如果校验器依赖外部库,用户要跑这个审计流程前得先装一堆包,万一网络环境受限或者依赖版本冲突,校验步骤直接卡住,整条六阶段流程里本该最稳的一环反而变成最容易出故障的一环。零依赖意味着只要有 Node.js 就能跑,这也和 README 里列出的环境要求对应。

动手上手

terminal

安装这个技能用的是 skills 这个命令行工具,从 GitHub 地址直接拉取:

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

执行后可验证的结果是本地会出现 security-audit 技能的文件,正常情况下 npx 会打印安装成功的提示,后续代理工具就能识别并加载这个技能。

技能装好之后,在编码代理里直接说一句自然语言指令就能触发审计:

security audit this codebase

这句话会触发全审计模式,按 README 的说明,默认输出会落在 ~/security-audit-skill//run- 这样的目录下,可验证的结果是审计结束后去这个路径查看,应该能看到 architecture.md、coverage-ledger.json、findings.json、REPORT.md 等一整套产出文件,文件名和阶段对应得上就说明流程走完了。

运行前要确认两个前提,一是用的编码代理所带的模型支持工具调用和并行子代理,二是本机装了 Node.js,用来跑零依赖的 findings 和 coverage-ledger 校验器。README 还提到理想情况下还需要一个操作系统强制的沙箱环境,用来跑目标代码的构建、测试等操作,这个条件没有的话,后面局限部分会说明具体影响。

应用场景

对内部代码库或者拉下来的第三方开源项目做全面安全审计,是最直接的用法,说一句 security audit this codebase 就能启动完整六阶段流程。

想针对某个子目录查漏洞也可以,输入 find security vulnerabilities in ./src 这类直接审计请求,一样会走全审计模式,只是范围收窄到指定目录。

多轮增量审计适合长期维护的项目。单次运行平均只能找到多轮累计发现总量的一半左右,对同一个仓库隔一段时间重复跑一次,代理会利用上一轮留下的覆盖账本和发现记录,把没查到的地方继续补上,而不是每次都从零开始扫一遍。

独立分析

stars compare

重复运行能明显提升覆盖率,README 给出的数据是单次运行大约只能找到多轮累计发现总量的一半,这个比例也说明了项目为什么把多轮运行设计成累加模式而不是每次独立重跑。如果每轮都从零开始,相当于每次都只能摸到一半的漏洞,长期来看效率很低。把覆盖账本和发现记录保留下来作为下一轮的起点,等于让审计有了记忆,这个设计思路比单纯堆更多轮次更实际。

和 Cloudflare 内部那套多阶段、全舰队漏洞发现系统相比,这个公开仓库只是起点版本。README 里说内部系统由这个技能演化并扩展而成,处理对象从单个仓库变成了整个舰队规模的代码库集合。公开版本里能看到的六阶段流程和校验机制,是经过内部实践验证后抽出来的基础骨架,内部版本在此之上大概率加了更复杂的调度和规模化处理,但那部分细节公开仓库里没有体现。

局限与风险

没有操作系统强制沙箱的环境下,审计流程不会去执行目标代码库里的代码,涉及需要跑构建、测试或者具体进程才能确认的发现,会一直停留在 needs_validation 状态,不会被标记为 confirmed。这意味着在普通本地环境跑这套流程,报告里可能会有相当一部分结论处于未决状态,需要人工再确认一轮。

防御纵深上的缺口不会被当作漏洞处理,只会记成 hardening note,也就是加固建议。如果团队期望的审计结果包含所有可以改进的安全配置点,这部分内容在 findings.json 里是分开记录的,不要和正式漏洞混为一谈。

公开的 README 没有给出示例输出,实际跑起来 REPORT.md 和 findings.json 具体长什么样,只能自己跑一次才知道,对第一次使用的团队来说需要一些摸索成本。

单次运行覆盖率有限这一点前面提过,如果团队只打算跑一次就下结论,大概率会漏掉一半左右本该发现的问题,这是这套工具设计上就承认的局限,不是使用不当造成的。

结论卡片

verdict

适合需要系统化、可追溯漏洞审计流程的安全团队,尤其是已经在用支持工具调用和并行子代理的编码代理的团队。不适合没有这类代理能力、只能跑简单问答式模型的用户,流程里分头狩猎和独立验证这两步都依赖并行子代理才能跑起来。想要效果最好,建议搭配 OS 强制沙箱一起用,这样发现才能从 needs_validation 真正推进到 confirmed,不然很大一部分结论会卡在待验证状态。


项目地址:github.com/cloudflare/…

原文地址:tools.wflynn.cn/aitools/git…

关注公众号「YourTools」,每天推送 GitHub 趋势与开源工具速报:

YourTools 公众号