Community编程与开发github.com

OrenSegal/audit

通过代码栈的每一个视角对代码库进行对抗性审计,验证每个发现,按根本原因聚类,以问题单地图交付修复,并理清结构。

audit 是什么?

这是 OrenSegal/audit,一个用于对代码库进行深入、多视角安全与质量审计的 AI 代理技能。其核心理念是让代理扮演“对手”,从不同角度(如输入、时序、用户或攻击者)质问代码,以发现可能导致错误答案、数据丢失、数据泄露或用户受阻的场景。该技能支持多个平台,包括 Claude Code、Cursor 和 Codex,并围绕一个基于文件的严格工作流组织:先扫描仓库以识别技术栈和热点,然后通过多个独立的“镜头”进行侦查,每个镜头针对特定方面(如安全、竞态条件等)。审计过程遵循方法论,如事前分析(pre-mortem)、逆向思维(inversion)和假设清单(assumption ledger),并生成严格的格式化发现。验证阶段会合并重复项、反驳发现,并通过覆盖率审查确保不遗漏关键路径。最终输出是一份详细报告和一张可操作的修复问题单地图,问题单通过用户批准的决策流程进行路由。该工具旨在生成结构化的、可复用的审计,帮助团队理解其代码的弱点,并以系统的、分步骤的方式优先处理修复。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/OrenSegal/codebase-audit/tree/HEAD/skills/audit

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

对该代码库执行一次对抗性审计并完成它。先报告和交付;仅在带 --fix 参数或用户选定修复后才修改源代码。

你是对手。每个镜头从不同角度提出一个问题:什么输入、时机、用户或攻击者会导致此代码给出错误答案、丢失数据、泄露数据或使用户受阻?

此文件夹包含审计所需的一切。从该文件所在目录解析以下路径:

  • lenses/<lens>.md:每个镜头一个文件。其 Fires: 行说明镜头何时运行(always,或 when <condition>)。每个探针要么是无条件的(始终回答),要么标记为 (when <condition>)(当条件满足时回答,否则关闭为不适用)。然后是镜头产生的工件,以及它的完成行。
  • scripts/scan.py:对仓库进行指纹识别,路由镜头,并列出项目自身的分析器来运行。scripts/signals.tsv:每个检测和种子模式;scripts/tools.tsv:它知道的每个分析器。项目在 docs/agents/audit-signals.tsv 中添加自己的行。
  • scripts/verify.py:对照镜头文件检查发现文件。scripts/cochange.sh:一起变更的文件。
  • DELIVER.md:交接说明、审计地图及其问题单。
  • UNTANGLE.md:结构重构,用于 --untangle 和结构性问题单。

1. 范围

  • 参数:路径(默认:仓库根目录);--lens a,b 仅运行这些镜头;--since REF 审计自某个引用以来的变更(PR 基础,或上次审计的提交);--fix;--untangle [area|ticket] 直接跳转到 UNTANGLE.md;--out DIR(默认 .audit/)。
  • 当无法获得答案时(CI,claude -p),未回答的问题留在 HANDOFF.md 中作为开放问题,交付仅进入本地跟踪器,并且除非问题单在 approved: 行上,否则源代码保持不变。
  • 创建输出目录,其中包含 .gitignore 和 *,因此审计不会触及任何已跟踪的文件。启动新运行时(绝不在恢复时),首先将之前运行的 RUN.md、REPORT.md 和 findings/ 移动到 <out>/history/<其日期>/,以便新运行可以与之比较。
  • 恢复:如果 <out>/HANDOFF.md 存在,则从其 next 阶段继续,运行的文件保留在原处。其 approved: 行上的问题单被清除,无需再次询问即可进行源代码更改;按照 DELIVER.md 的说法,处理边界上的第一个问题单,每个会话一个问题单。任何其他问题单首先返回给用户。如果在 history/ 中存在更早的运行,则提供 --since <其提交> 并向前携带 refuted.md。

每个阶段结束时按照 DELIVER.md 的描述重写 <out>/HANDOFF.md。

2. 扫描与侦查

运行 python3 scripts/scan.py <path> [--since REF] [--lens a,b] > <out>/SCAN.md,因此 SCAN.md 是脚本的原始输出:技术栈、包、哪些镜头触发及原因、热点、执行计划、需要运行的分析器、每个探针的候选位置(最热的文件优先),以及特殊情况计数。

运行工具下列出的每个可用命令的分析器,将其输出保存到 <out>/tools/<tool>.txt。它们的警告是它们命名的镜头行的线索,与扫描位置相同;缺失或失败的工具在 RECON.md 中记录,绝不安装。

然后编写 <out>/RECON.md,完成脚本无法看到的内容。每个标题都有答案或 none 时才完成:

  • 边界:每个外部数据进入的地方(HTTP、webhooks、数据库读取、文件、环境变量、深层链接、推送负载、模型输出、用户输入)。
  • 持久化:本地存储、服务器数据库、缓存、队列,以及每个事实归谁所有。
  • 关键路径:金钱、认证、数据删除、迁移、任何与安全相关的内容、主要用户循环。
  • 命令:构建、测试、lint、运行;测试当前是否通过。
  • 内部规则:CLAUDE.md/AGENTS.md;GLOSSARY.md(或 GLOSSARY-MAP.md)中的领域语言,用于发现和修复中的所有名称;ADR,其中已接受的风险在风险未改变时保持已解决;docs/agents/ 中的问题跟踪器。
  • 条件:对于每个触发的镜头,在此处哪些条件性探针成立,并附有证据。
  • 镜头覆盖:扫描跳过但侦查显示需要的镜头,或由错误信号触发的一个,并附有理由。

编写 <out>/RUN.md:提交、日期、参数、最终镜头列表。

3. 搜寻

遵循扫描的计划:顺序执行此处每个镜头,一个接一个;并行 为每个镜头分配一个子代理,分片镜头为每个列出的包分配一个子代理。限制并发的主机分批次运行,将镜头与站点最少的配对;没有子代理的主机按顺序运行所有内容。

子代理启动时不携带任何技能和此对话的任何部分,因此每个简报独立。它包含:镜头文件、此文件(用于方法和发现格式)、RECON.md、SCAN.md 中镜头对应的部分、范围以及输出路径 <out>/findings/<lens>[-<package>].md。搜寻者只读:他们阅读代码、运行测试、脚本和应用,仅写入其发现文件和重现步骤,然后返回主上下文,主上下文单独分发。

方法

  • 事前分析:发布三个月后,第一条差评是关于这个领域的。写下来,然后找到导致它的代码。
  • 逆向思维:你如何使这个功能尽可能严重地失败?检查每种方式的代码块。
  • 假设清单:对于关键路径上的每个函数,列出它的假设。哪些假设通过类型或约束得到强化,哪些靠运气?
  • 切斯特顿栅栏:在将守卫、特殊情况或奇怪的一行称为错误之前,先找到它存在的原因(git log -L、blame、PR)。有活生生理由的栅栏不是发现。
  • 候选是线索:扫描站点是开始阅读的地方。零站点的探针仍要回答,站点只有在有具体场景时才成为发现。

发现格式

### <LENS>-<n> <60 字符以内的声明>
- where: 路径:行号
- probe: <镜头文件中的探针ID>
- scenario: <具体的输入、状态或时机> → <用户或系统看到的错误结果>
- severity: critical | high | medium | low
- detectability: loud(崩溃、告警、测试失败)| quiet(人们可能注意到的错误答案)| silent(没人会注意到)
- verdict: CONFIRMED(重现它的测试、脚本、查询或截图)| PLAUSIBLE(有推理,未运行)
- fix family: <变更的类型,而非补丁>

严重性:critical 导致数据丢失或损坏、违反安全或隐私、金钱计算错误或危及安全;high 在常见路径上显示错误答案或使用户受阻;medium 在罕见路径上如此或降低质量;low 是卫生。严重性由谁在已交付的配置中今天可触发它决定:critical 或 high 场景命名该人(任何访客、任何登录用户、持有 X 的攻击者);仅操作员或死配置可达的路径降低一级。

编辑:发现、重现、报告和问题单会共享。在任何秘密、令牌或个人数据的位置写入 <REDACTED>,并指向其存储位置而非引用它。

发现文件以镜头的工件开头。每个探针以至少一个发现或一个 clean: 行结束:clean: <probe> — <evidence>,或者对于条件不成立的条件性探针:clean: <probe> — n/a: <why>。当探针的完成行成立且 python3 scripts/verify.py <out> --root <path> --lens <lens> 通过时,搜寻者完成。

4. 验证

  1. 合并重复:跨镜头,当两个发现共享位置和机制时,保留更严重的那块,添加 - also: <the other ids>,并删除另一块,使每个问题只出现一次。
  2. 反驳:每个 critical 或 high 发现获得一个新的反驳者;其余按镜头分批。反驳者仅获取发现块,绝不包括搜寻者的推理。对于 PLAUSIBLE 发现,它试图驳斥声明:上游守卫、数据库中的约束、不可达路径、有理由的栅栏。对于 CONFIRMED 发现,它检查重现:它是否因所述原因变红,且通过真实用户或攻击者可达的代码?当主机提供不同的模型时,反驳者使用它,因为共享偏差使同模型一致性成为弱证据。
  3. 按证据提升:存活并已重现 → CONFIRMED;存活但仅凭推理 → PLAUSIBLE;被驳斥 → <out>/refuted.md 并附理由。
  4. 覆盖率审查:一个全新的子代理获取 RECON.md 的关键路径和每个镜头的 clean: 行,并命名每个证据薄弱的关键路径(需要跟踪或测试的句子)或没有镜头触及的路径。每个路径在被报告之前,返回到匹配的镜头进行二次查看。

重现是一个紧凑的反馈循环,对此发现变红而不是其他:在最接近的接缝处编写一个失败的测试、脚本或查询。只要成本低于十分钟,就构建一个,放在 <out>/repro/ 中,仅针对本地、分支、沙箱或测试模式的系统。被一个下一季度仍会成立的理由(已接受的风险、有意的权衡)驳斥的发现属于 ADR,在交付时提供,以便后续审计在侦查中读取。

5. 报告

编写 <out>/REPORT.md:

  1. 摘要:按严重性和镜头统计,以及优先修复的前三个问题及原因。
  2. 修复:按根本原因聚类发现,每个修复写在其解决的发现之上;寻找一个修复背后的多个发现,这通常看起来与它们完全不同。标记每个为 structural(耦合、重复、缺失类型、浅层模块、放错的接缝)或 local(一个地方、一次更改),并用深层模块词汇描述结构性修复:模块、接口、深度、接缝、适配器、杠杆、局部性、删除测试。
  3. 未聚类的发现,按严重性排序,然后按可检测性(先静默),再按可达性。
  4. 覆盖率:每个镜头的 clean: 行、跳过的镜头及其原因、运行或缺失的分析器、以及覆盖率审查返回的内容。
  5. 自上次审计以来,当 history/ 包含更早运行时:已修复、仍开放、新出现、以及回归(之前修复过,现在又回来)。
- 让服务器成为 `scan_count` 的唯一写入者,使用 `where scan_count > 0` 原子递减,这样客户端不能漂移、双重消费或重置它。[structural, critical]
  - MONEY-2 `ScanQuota.swift:40` 在上传前本地递减,并在重试时再次递减。
  - MONEY-3 重新安装应用将本地存储中的 `scansUsed` 重置为 0。
  - STATE-5 每周配额在设备的本地周一重置,因此向西飞行可获额外一周。

运行 python3 scripts/verify.py <out> --root <path>;当它通过时报告完成。当主机渲染结构化发现(ReportFindings 工具)时,也要报告每个存活的发现,最严重的优先。

调优此项目的漏斗:一个种子行其所有站点最终被驳斥或干净,或者一个指向它的发现没有种子,被视为项目 docs/agents/audit-signals.tsv 的建议行。在报告中列出建议;仅在用户接受时才写入。

6. 交付与交接

阅读 DELIVER.md。将报告绘制为一张审计地图,每个修复一个票据,有类型,有阻塞边,放在仓库的问题跟踪器上(未配置时放在本地 .scratch/;在发布到远程跟踪器之前确认)。然后询问要开始哪些修复作为一个烧烤轮:将每个编号为一个问题,并附上你推荐的答案,措辞使得“是”接受它。如果使用 --fix,则采纳所有建议。在 HANDOFF.md 的 approved: 行记录已批准的票据编号。

根据票据的形状路由每个票据。命名的技能是 mattpocock-skills;当可用时使用 Skill 工具调用一个,否则内联执行其步骤:

票据形状路由
需要先决策:接缝的位置、与之矛盾的 ADR、模糊的领域术语、要接受的风险grill-with-docs,将答案作为 ADR 和术语记录
结构性,一个模块,值得在提交前与用户探讨improve-codebase-architecture 针对该区域
结构性,有竞争的接口设计codebase-design,其双重设计模式
结构性,方法明确且适合一个会话UNTANGLE.md,附带票据和 REPORT.md 作为其起始列表
结构性,大于一个会话wayfinder,绘制决策票据以到达目的地
许多修复需要切片以便代理无人值守工作to-tickets(曳光弹切片、阻塞边、大型重构作为展开-收缩),然后 implement
本地修复tdd:重现是第一个红测试,在与用户商定的接缝处;整个测试套件保持绿色
PLAUSIBLE 且 critical,尚无重现diagnosing-bugs 阶段 1:先构建紧凑循环

当边界为空时,使用 --since <审计提交> 重新审计。审计的目标是通过一个重新审计来验证没有存活的 critical 或 high 发现。

完成条件

  • 每个触发的镜头都有一个满足其完成行的发现文件,并且 verify.py 对整个输出通过。
  • 每个存活的发现都有位置、探针、场景、严重性、可检测性和判定;每个被驳斥的都位于 refuted.md 中。
  • REPORT.md 将每个发现置于一个修复下或未聚类列表中,地图每个修复对应一个票据,并且 HANDOFF.md 指明下一个票据。

相关技能