AI 生成代码的安全审计不能靠”人眼看一遍”,真正可行的做法是:把 SAST 、依赖漏洞检查、密钥扫描固定成每一次 PR 的必跑项,再给认证、授权、加密、支付这几类文件单独加一道人工门槛。 GitHub 官方给出的数字是,Copilot 驱动的 code scanning autofix 已能为 90% 以上的漏洞类型生成修复建议,其中超过三分之二几乎不用改就能合并——缺的从来不是修复能力,而是把检查钉进流程的那道闸门。
为什么 AI 生成代码需要单独一套审计
- 模型会复现训练语料里的漏洞模式:字符串拼接的 SQL 、未校验的文件路径、不安全的反序列化,这些在 AI 输出里出现的频率并不比手写低。
- 产出速度让人工复核失效:一个下午能开十几个 PR,逐行读根本不现实,最后退化成”看起来能跑就合并”。
- 依赖选择成了新的风险面:编码智能体在 PR 时选到”当时已知有漏洞”的包版本的概率高于人类,因为它的知识快照滞后于 Advisory 数据库。
- 模式匹配的 SAST 抓不到越权:跨函数数据流、对象级权限缺失这类问题需要上下文判断,静态规则覆盖不到。
三类必须自动化的检查
| 检查类型 | 抓什么 | 典型工具 | 建议策略 |
|---|---|---|---|
| SAST | 注入、 XSS 、路径遍历、不安全反序列化 | CodeQL 、 Semgrep | 每次 PR 必跑,高危阻断 |
| SCA | 依赖版本已知漏洞、恶意包 | Dependabot 、 Advisory DB | 高危阻断,低危自动提 PR |
| 密钥扫描 | 硬编码 token 、私钥、连接串 | Secret scanning | 发现即阻断,无例外 |
| IaC / DAST | 部署清单、可访问服务的运行时问题 | Checkov 、 DAST 工具 | 视团队成熟度选配 |
落地:把门槛写进 CI
关键不是装了什么工具,而是合并前必须过闸。以 GitHub Actions 为例,最小可用配置大致是这样:
# .github/workflows/security.yml
name: security-gate
on: [pull_request]
jobs:
codeql:
runs-on: ubuntu-latest
permissions: { security-events: write, contents: read }
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with: { languages: javascript-typescript, python }
- uses: github/codeql-action/analyze@v3
deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm audit --audit-level=high # 返回非 0 即失败
secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: gitleaks/gitleaks-action@v2
然后在分支保护里把这三个 job 设为 required status checks 。阈值建议直接写死:CVSS ≥ 9.0 的告警阻断合并,绕过必须走书面例外并留痕;没有例外通道的闸门,最后一定会被人为绕过。
人工复核只盯这四类改动
自动化覆盖不到的地方,人力要集中投在下面这几类文件上:
- 认证、会话、权限判断逻辑
- 支付与金额计算
- 密码学相关代码(不要让 AI 自选算法,更不要让它自己实现)
- 会触碰生产数据的数据迁移脚本
这里还有一条容易被忽略的规则:请求者不能是审阅者。让写提示词的人自己审 AI 产出,或者让一个 AI 去批另一个 AI 的 PR,等于没有审。分支保护要排除 bot/agent 身份,至少要求一个真实 human approval 。
用 AI 审 AI 的正确姿势:先枚举,再审计
GitHub Security Lab 公开的 taskflow 框架给出了一个很值得抄的三段式结构:
- 信息收集:识别组件、入口点、 Web 入口点、预期用法,写进数据库供后续步骤复用。
- 风险建议(只建议,不审计):让模型基于”这个组件会不会吃不可信输入、是否涉及高权限动作”来提风险类型,并明确禁止它在这一步直接下结论。
- 逐条审计:换一份干净上下文,逐个验证上一步的建议,要求给出文件路径 + 行号 + 真实攻击场景,并明确允许得出”这里没有安全问题”。
把”建议”和”审计”拆成两个上下文,是抑制幻觉的关键;允许模型说”没问题”,是避免它硬凑漏洞的关键。我们在把 AI 编程接进 CI 流水线里讲的也是同一个思路——能自动化的交给机器,判断留给流程。
一份可复用的审计提示词骨架
你是安全审计员。针对组件 {component}:
1. 列出它可能接收的不可信输入来源;
2. 列出 3-5 个值得查的漏洞类型,只列不查;
3. 逐条查源码,每条必须给出 file:line 与具体攻击场景;
4. 如果确认不存在漏洞,明确写"未发现安全问题",不要编造。
禁止把"配置不当""系统已被攻陷"作为攻击前提。
三个常见坑
- 只装一个扫描器:语言或规则集覆盖不到的地方就是盲区,至少 SAST + SCA 双开。
- 告警当噪音关掉:高危被忽略等于没扫,要么修要么走例外流程,不要静默。
- 把 autofix 当终审:自动修复同样需要人工复核,尤其是它顺手加进来的新依赖,必须确认在包注册表里存在且无已知漏洞。







评论 (0)