审计 ≠ review。审计挖特定 bug 家族:竞态、null、off-by-one、泄漏。下面这些 Prompt 各打一类。
适合哪些场景
即将发布的 on-call 工程师、独立部署代码的创业者、不能出回归的安全相关团队、正在追事故根因的人。
什么时候不建议这样写 Prompt
玩具脚本、一月才跑一次的自动化别用——成本不划算。也不要把审计和重构塞进一个 Prompt,两个目标分两次跑。
Prompt 结构公式
Bug 审计 Prompt 一定要带这六个要素:
- Bug 家族:每次只挑一种——竞态 / null / off-by-one / 泄漏 / 时区,绝不是”找所有 bug”。
- 范围:哪些文件 / 函数 / commit,把搜索面圈住。
- 失败场景:要求描述触发的输入或交错,而不是只贴个标签。
- 证据:每条 finding 给
file:line+ 具体复现 / 测试思路。 - 严重度:Critical / High / Med,强迫排序而非平铺。
- 输出格式:编号清单或
file | line | 场景 | 修复表格。
这套 Prompt 适合用在哪
- 发布前审计
- 继承代码库调试
- 事故根因
- 重构前安全网
- 上线前回归扫描
13 个可直接复制的 Prompt 模板
1. 竞态条件
审查竞态、共享状态变更、缺锁。每条:file:line、两线程冲突场景、缓解。
{粘贴}
2. null / undefined
审查可能 null/undefined 解引用。列出输入可能为 null 但没检查的调用点。
{粘贴}
3. off-by-one
查 off-by-one:循环边界、切片、分页、日期算术。每条:file:line、场景、修复。
{粘贴}
4. 错误处理审计
审错误处理:吞掉的错、通用 catch、缺上下文。列每处 + 建议日志 / 传播。
{粘贴}
5. 资源泄漏
审资源泄漏:文件、DB 连接、事件监听、订阅、定时器。标所有 open-without-close。
{粘贴}
6. 时区 bug
审时区:隐式本地时间、naive datetime、DST 期间转换。每条 + 可能失败方式。
{粘贴}
7. 状态机不一致
下面是状态机流程。列不可能状态、不可达转换、缺 guard。给一个更清模型。
{粘贴}
8. 边界输入
为每个函数列边界输入(空、单个、最大、负、特殊字符、unicode、极大)行为不明的。各建议测试。
{粘贴}
9. 浮点 / 金额计算
Audit this code for floating-point / money-arithmetic bugs: `0.1 + 0.2` accumulation drift, currency rounding at the wrong layer, mixing cents and dollars, division-before-multiplication losing precision, tax / discount applied in inconsistent order. For each: file:line, the input that produces wrong totals, suggested fix (Decimal type, BigInt cents, etc.).
{paste}
优化建议: 处理订单 / 发票时追一句:“Also flag any place where rounding happens twice in the same calculation chain.”
10. 幂等 / 重试
Audit for retry-safety bugs: external API calls without idempotency keys, DB writes that double-fire on retry, webhook handlers that are not idempotent, message consumers without dedupe. For each: file:line, what double-fires, suggested key/window/dedupe strategy.
{paste}
11. 缓存一致性
Audit for cache bugs: writes that update DB but not cache, cache keys that miss tenant/user scoping, stale reads after writes, TTLs longer than the data's natural change rate, cache stampede risk. For each: file:line, stale-read scenario, fix sketch.
{paste}
12. Unicode / 编码
Audit for string/encoding bugs: byte-length vs character-length confusion, `toLowerCase()` on non-ASCII, slugs that drop emoji or CJK, surrogate-pair truncation, normalization (NFC vs NFD) mismatches across DB/UI, header/URL decoding inconsistencies. For each: file:line, an input that breaks, fix.
{paste}
13. 审计发现 → 最小失败测试
最后跑。把每条 finding 转成可运行的测试用例。
Take each finding from the bug audit above and write the minimal failing test that reproduces it in {framework}. Each test: one assertion, deterministic input, no mocks unless strictly needed. Mark which tests fail today vs which need infra (DB / queue / timezone faking).
Findings: {paste}
可替换变量: framework(如 vitest / jest / pytest / go test)
容易踩的坑
- “找所有 bug” 混类别
- 发现没 file:line
- 不复核就信 AI 置信
- 让审计同时给修复——诊断被搅乱
- 没把 finding 转成测试——审计变成只读文档
优化技巧
- 每次只跑一个家族(竞态 / null / 泄漏 / 时区),交叉会稀释。
- 每条 finding 要 触发场景而不仅是标签——“这里有竞态”容易幻觉,“A 在 B 之后 C 之前完成时”才能复核。
- 配模板 13 把 finding 写成最小失败测试,只有测试能证明 bug 真实。
- 大仓库让 Claude Code 用
Grep找危险模式(catch (e) {}、setTimeout、Date()再审计。 - 加置信度门槛:“Only report findings you would bet $50 on.”——噪音降 40%。
- 修完再用同一 Prompt 跑一遍:如果新的 file:line 还出现,说明是系统性问题。
- 在 Prompt 里维护一个 “ignore list” 装已知误报,每次不会反复刷出来。
FAQ
- Bug 审计和 code review 有什么区别?: Review 看 diff;审计看整个模块/仓库且深扎一个 bug 家族。互补,不可替换。
- 多久跑一次 bug 审计?: 大版本发布前、接手代码库后、事故后审失败模块、生产关键路径每季度一次。
- 为什么 AI 偶尔漏掉明显 bug?: 通常因为它看不到调用点或类型定义。要么扩上下文,要么用 Claude Code / Cursor 让 agent 自己
Read。 - 可以相信 AI 给的 severity 吗?: 当起点。最终要按业务影响重排——AI 不知道哪条路径承载收入。
- 误报怎么办?: 20-30% 的误报是常态。漏掉真 bug 的代价通常大于复核误报,接受这种不对称。
- AI 可以顺手把 bug 修了吗?: 可以,但要单独再开一次。诊断和修复混在一起会让两边都变差。