安全审计 Prompt:让 AI 找出代码里的安全漏洞
让 AI 按 OWASP Top 10 逐项对照代码检查:注入、鉴权绕过、敏感信息泄露、不安全反序列化等,每条给出风险等级、可利用路径与修复建议,可直接进安全评审。
发布 2026-06-21更新 2026-10-13用法
把需要审计的代码粘进来。适合 review 一个文件或一个模块,不要一次粘整个项目。
什么时候用 / 别用
用它:
- 一个具体的文件或模块(典型是 Controller / 中间件 / 数据访问层)要在合并前过一遍。
- 你接手了别人的代码,需要快速画出「哪些地方碰了外部输入」的地图。
- 要写安全测试用例之前,先让 AI 列出候选攻击面,再由人来筛。
别用:
- 一次粘整个仓库。OWASP 十类清单在超大上下文里会退化成逐条念清单,命中率反而低于单文件。
- 指望它替代 SAST / 依赖扫描。AI 擅长的是「这段拼接有没有注入」,不擅长「这个依赖版本有没有 CVE」——后者请交给
npm audit/pip-audit/trivy,两者是互补不是替代。 - 要对外承诺合规结论(等保、PCI-DSS、SOC 2)。本 prompt 的产出是候选问题清单,不是审计意见。
- 加密协议 / 随机数 / 密钥派生的实现细节。这类代码「看起来没问题」和「真的没问题」之间隔着密码学评审,AI 会自信地给出错误答案。
最容易犯的错:把「AI 说未发现风险」当成「没有风险」。这条 prompt 的产出上限是「人类审计员的输入」,不是「审计结论」。
Prompt
你是一个应用安全专家。请对以下代码进行安全审计,按 OWASP Top 10 逐项检查。
## 代码
{{粘贴代码}}
## 技术栈
- 语言:{{Python / JavaScript / Go / Java}}
- 框架:{{Express / FastAPI / Django / Spring}}
- 数据库:{{PostgreSQL / MySQL / MongoDB}}
## 检查清单
### A01 — 访问控制失效
- 未授权可访问的接口
- 越权(水平/垂直)风险
- IDOR(不安全直接对象引用)
### A02 — 加密失败
- 明文传输敏感数据
- 弱加密算法(MD5、DES)
- 硬编码密钥/密码
### A03 — 注入
- SQL 注入(拼接 SQL 语句)
- 命令注入(拼接 shell 命令)
- LDAP/XPath 注入
### A04 — 不安全设计
- 敏感操作缺少速率限制
- 缺少 CSRF 防护
- 不安全的文件上传
### A05 — 安全配置错误
- 调试模式未关闭
- 不安全的默认配置
- 错误信息泄露堆栈
### A06 — 易受攻击的组件
- 已知漏洞的依赖版本
### A07 — 认证失败
- 弱密码策略
- 会话管理缺陷
- JWT 配置问题
### A08 — 数据完整性失败
- 反序列化漏洞
- 不安全的 CI/CD
### A09 — 日志监控不足
- 安全事件未记录
- 日志包含敏感信息
### A10 — SSRF
- 服务端发起未验证的 HTTP 请求
## 输出格式
对每个发现:
- **[严重度] 漏洞类型 — 文件:行号**
- 问题描述:为什么这是漏洞
- 攻击场景:怎么利用
- 修复建议:给出修复后的代码
如果没有发现问题,明确写「未发现 A0X 风险」。
严重度定义
- 严重 — 可直接被利用,导致数据泄露或 RCE
- 高危 — 需要特定条件才能利用,但影响严重
- 中危 — 增加攻击面,但单独无法直接利用
- 低危 — 最佳实践问题,建议修复
为什么有效
- 按技术栈限定检查清单:通用清单会给出一堆你框架里根本不存在的风险,噪音大到没人看;限定栈之后命中率陡增。
- 要求给可复现的 PoC 思路:只有「这里有 SQL 注入」没有「怎么触发」,开发无法验证、也无法判断优先级。
- 严重度定义写进 prompt:不同 Agent 对「高危」的理解差三个等级,不定义就无法排序。
进阶(自动化)
把审计接进 PR 流程,但只卡「严重」级别,避免噪音导致忽略:
changed=$(git diff --name-only origin/main...HEAD -- "*.ts" "*.py")
[ -n "$changed" ] && ai-audit --files "$changed" --min-severity high
更完整的自动化方案见 AI 代码审查工具横评;把审查接进 CI 阻断合并的完整步骤见 AI PR Review 流水线 Playbook。
CI 里不要直接
--fail-on high就上线。先跑两周「只报告不阻断」,统计误报率,再把阈值调到你团队能承受的水平——安全门禁一旦误报太多,开发者会想办法绕过它,那时它比没有更危险。
验收判据:怎么判断这次审计是可信的
安全类 prompt 的误报特别贵(开发者会去「修」一个不存在的漏洞,或者反过来忽略真问题)。用这四条:
| 判据 | 具体做法 | 不合格的典型信号 |
|---|---|---|
| 每条都有触发路径 | 逐条对照「攻击场景」,问「这个输入真的能到达这行吗」 | 只有「建议使用参数化查询」而没有具体入口 |
| 能真的复现 | 挑 1 条高危,在测试环境构造那个请求 | AI 给出的 payload 在你的框架里被中间件拦掉了——说明它没读全栈 |
| 严重度可排序 | 看它是否真的用了你定义的四级 | 所有条目都是 或全是 ,等于没有排序 |
| 「未发现」有分项 | 检查是否逐条写了「未发现 A0X 风险」 | 只写一句「整体安全性良好」——这是安全审计里最危险的一句话 |
变体
A. 只审外部输入(压误报最有效的一招)
先列出这个文件里所有「来自外部、未经本文件校验」的输入点(HTTP 参数、header、
消息体、环境变量、文件内容、上游 RPC 返回值)。
只针对这些输入点做 OWASP 检查;不涉及的检查项直接写「不适用」并说明原因。
B. 让它给出可验证的 PoC,而不是结论
对每个高危发现,给出:① 一个可直接 curl / 直接调用的最小请求;
② 期望的异常行为;③ 修复后同一请求的期望行为。
给不出 ① 的,降级为中危并注明「未构造复现」。
C. 管道化:只对本次改动跑,并落盘成报告
changed=$(git diff --name-only origin/main...HEAD -- "*.ts" "*.py")
[ -n "$changed" ] && for f in $changed; do
echo "### $f"; claude -p "$(cat prompts/security-audit.txt)" < "$f"
done > /tmp/audit.md
# 只把高危及以上提给人工
grep -E '^\[(严重|高危)\]|🔴|🟡' /tmp/audit.md
claude -p是非交互管道模式;Codex、Gemini CLI、OpenCode 同理。安全审查结果必须落盘成可追溯产物,不能只留在对话里——否则复现记录和「谁在什么版本上审的」都会丢。
反例(AI 默认会写的烂版本)
默认输出:「建议使用参数化查询」「注意 XSS 风险」「确保做好权限校验」——正确的废话,没有文件行号也没有触发路径。
加了 prompt 之后:[严重] src/user/repo.ts:31 — SQL 字符串拼接,入参来自 req.query.sort;触发:GET /users?sort=id;DROP TABLE users;修复:改用参数化查询或白名单映射字段名。
延伸阅读
- Staff 级 Code Review Prompt · PR Review 第一道筛 — 通用审查里也覆盖安全项
- 搭一条自动化 PR Review 流水线 — 把安全审查接进 CI 阻断合并
- AI 代码审查工具横评 — 带安全扫描的自动化工具