安全
这一课你将能做到
- 用「AI 生成代码安全审查清单」逐项检查注入、密钥泄露、依赖幻觉三大风险
- 配置自动化安全扫描工具(SAST、依赖检查)进 CI,形成兜底
- 建立团队级的 AI 使用安全规范,防止敏感信息泄露给 AI
为什么要学
AI 生成代码的安全风险不是「AI 故意害你」,而是「AI 不知道什么是安全的」。它训练数据里有大量不安全的代码示例( Stack Overflow 上的快糙猛答案、教程里的简化示例),它会不加区分地复现这些模式。
人话:AI 是个博览群书但没有安全意识的实习生。它知道一百种实现「拼接 SQL」的方法,但不知道哪一种会注入;它记得无数教程里的硬编码密钥示例,但不知道密钥不能进代码。
真实项目中,AI 代码的安全审查必须显性化、清单化、自动化——不能靠「我觉得这段代码没问题」,要靠「清单逐项过了没有」。
先建立图像
AI 生成代码的三大安全风险:
┌─────────────────────────────────────────┐
│ 1. 注入风险 │
│ SQL 注入、XSS、命令注入、路径遍历 │
│ AI 复现训练数据里的不安全模式 │
├─────────────────────────────────────────┤
│ 2. 密钥泄露 │
│ 硬编码密码、API key、内部域名 │
│ AI 从训练数据里学来的「示例习惯」 │
├─────────────────────────────────────────┤
│ 3. 依赖幻觉 │
│ 编造不存在的包名、推荐恶意包 │
│ AI 的「幻觉」+ 供应链攻击的温床 │
└─────────────────────────────────────────┘
跟着做
步骤 1:建立「AI 代码安全审查清单」
每次 AI 生成代码后,按清单逐项检查:
## AI 生成代码安全审查清单
### 注入风险
- [ ] SQL:是否用了参数化查询?(检查所有 SQL 拼接)
- [ ] XSS:用户输入是否转义后才渲染?(检查前端模板)
- [ ] 命令注入:是否用了 Runtime.exec 或 ProcessBuilder?参数是否过滤?
- [ ] 路径遍历:文件路径是否做了规范化?(检查 ../ 处理)
- [ ] LDAP/XML/XXE:相关解析是否禁用外部实体?
### 密钥与敏感信息
- [ ] 代码里有没有硬编码的密码、API key、token?
- [ ] 配置文件的示例值是不是真实凭证?
- [ ] 日志里会不会打印敏感信息(密码、身份证号、token)?
- [ ] 错误信息会不会泄露内部结构(表名、字段名、堆栈)?
### 依赖与供应链
- [ ] 新引入的依赖是否真实存在?(去 Maven Central / npmjs 验证)
- [ ] 依赖版本是否是最新稳定版?(检查是否有已知漏洞)
- [ ] 依赖的许可证是否合规?(GPL 传染性检查)
### 其他
- [ ] 权限校验:每个接口是否检查了调用者权限?
- [ ] 数据校验:所有外部输入是否做了校验(类型、长度、格式、范围)?
- [ ] 加密:敏感数据是否加密存储?(密码用 BCrypt,不用 MD5/SHA1)
步骤 2:逐项检查一个真实案例
让 AI 生成一个「用户登录接口」,然后按清单审查:
// AI 生成的代码(有安全问题)
@PostMapping("/login")
public Result<String> login(String username, String password) {
// 问题 1:SQL 注入
String sql = "SELECT * FROM user WHERE username = '" + username +
"' AND password = '" + password + "'";
User user = jdbcTemplate.queryForObject(sql, User.class);
// 问题 2:密码明文比较
if (user != null && user.getPassword().equals(password)) {
// 问题 3:token 硬编码密钥
String token = JWT.create()
.withSubject(username)
.sign(Algorithm.HMAC256("secret123")); // 硬编码密钥
return Result.success(token);
}
return Result.error("登录失败");
}
审查结果:
- SQL 注入:字符串拼接 SQL,必须用参数化查询
- 密码明文:数据库里密码必须 BCrypt 加密,比较时用 BCrypt.checkpw
- 硬编码密钥:JWT 密钥必须进配置,不能硬编码
步骤 3:让 AI 自己修复安全问题
把审查结果反馈给 AI:
修复以下安全问题:
1. SQL 拼接改成参数化查询(用 MyBatis-Plus 或 JdbcTemplate 的 ? 占位符)
2. 密码用 BCrypt 加密存储和校验
3. JWT 密钥从配置文件读取,不要硬编码
4. 登录失败时返回模糊信息(「用户名或密码错误」),不要区分「用户不存在」和「密码错误」
AI 修复后再按清单复查一遍。
步骤 4:配置自动化安全扫描进 CI
人工清单是第一道关,自动化扫描是兜底:
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# 1. 依赖漏洞扫描
- name: Dependency Check
run: mvn org.owasp:dependency-check-maven:check
# 2. 静态代码安全扫描(SAST)
- name: SpotBugs Security Audit
run: mvn spotbugs:check -Dspotbugs.includeFilterFile=security-filter.xml
# 3. 密钥泄露扫描
- name: Secret Scan
run: |
docker run -v $(pwd):/src zricethezav/gitleaks:latest detect --source /src
步骤 5:建立团队级 AI 使用安全规范
写进团队规则文件:
## AI 使用安全规范
### 禁止喂给 AI 的信息
- 生产环境的数据库连接串、密码、API key
- 用户的真实个人信息(姓名、身份证、手机号)
- 未公开的内部系统架构图、域名、IP
### 必须人工审查的 AI 代码
- 涉及认证、授权、加密的代码
- 涉及 SQL、命令执行、文件操作的代码
- 涉及第三方依赖引入的代码
### 自动化兜底
- CI 必须跑依赖漏洞扫描(OWASP Dependency-Check)
- CI 必须跑静态安全扫描(SpotBugs Security Plugin / SonarQube)
- CI 必须跑密钥泄露扫描(gitleaks / truffleHog)
讲清楚要点
- AI 不知道什么是安全的:它复现训练数据里的模式,包括不安全的模式。安全审查不能假设 AI 懂安全。
- 注入风险是 AI 代码的重灾区:SQL 拼接、命令拼接、路径拼接——AI 从教程里学来的「简化写法」恰好是最不安全的写法。
- 密钥泄露是 AI 的「习惯」:训练数据里无数教程用硬编码密钥做示例,AI 会不加区分地复现。所有密钥必须进配置或密钥管理服务。
- 依赖幻觉是新型供应链风险:AI 可能编造不存在的包名,或推荐已被弃用/有漏洞的包。新依赖必须人工验证存在性和安全性。
- 人工清单 + 自动化扫描 = 双保险:清单覆盖「AI 常犯的具体错误」,扫描覆盖「人可能遗漏的已知漏洞」。
你可能会懵的地方
-
AI 生成的代码里发现安全问题,是 AI 的锅还是我的锅? 你的锅。无论代码是谁生成的,合入仓库、部署上线的人是你,安全责任就是你的。这也是为什么安全审查不能省。
-
AI 能帮我做安全审查吗? 能,但不能替代人工。让 AI 审查自己的代码(「检查这段代码的安全问题」)有盲区——它可能不知道自己不知道什么。正确做法:AI 生成代码 → 人工按清单审查 → 自动化扫描兜底。
-
怎么防止 AI 把敏感信息泄露给模型服务商? 不把生产凭证、用户数据、内部架构喂给 AI;使用工具的 Privacy Mode 或企业版(不用于训练);敏感项目用内网部署的开源模型。
-
AI 推荐的依赖包怎么验证安全性? 三步:1. 去 Maven Central / npmjs 搜索确认包存在;2. 查 CVE 数据库或 Snyk 确认无已知漏洞;3. 看下载量和维护状态(半年没更新的包慎用)。
-
安全扫描工具会不会误报太多? 会。初期按「高危必改、中低危评估」处理,逐步调优规则。误报多的规则可以临时排除,但排除项要记录并定期回顾。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| SQL 字符串拼接 | SQL 注入 | 参数化查询(MyBatis-Plus / JdbcTemplate ? 占位符) |
| 密码 MD5/SHA1 哈希 | 彩虹表可破 | BCrypt/Argon2 加盐哈希 |
| 硬编码密钥进代码 | 密钥泄露,无法轮换 | 配置中心 / 环境变量 / 密钥管理服务 |
| 错误信息返回堆栈 | 泄露内部结构 | 生产环境返回模糊错误,堆栈只进日志 |
| 用户输入直接渲染 | XSS | 转义后渲染,富文本用白名单过滤 |
卡点急救
- AI 生成的代码有 SQL 注入,但业务逻辑复杂不好改:最小改动——把拼接改成参数化,其他逻辑不动。安全修复优先,重构随后。
- 依赖扫描报高危漏洞,但升级版本会破坏兼容性:先评估漏洞是否可达(你的代码是否真的调用了有漏洞的方法),不可达可以临时豁免;可达必须升级,兼容性破坏单独修。
- AI 把示例密钥写进了代码,已经提交了:立即轮换密钥(改密码、重新生成 API key),然后用 git filter-branch 或 BFG 清理历史,强制推送。
面试常问
-
AI 生成代码的安全审查流程是什么? 高分回答:三层——人工按清单审查(注入/密钥/依赖/权限/校验/加密)、AI 辅助自查(让 AI 列出自己代码的安全风险,作为参考)、自动化扫描兜底(SAST + 依赖检查 + 密钥扫描进 CI)。强调「AI 不知道什么是安全的,审查不能省」。
-
如何防止 AI 引入供应链攻击? 新依赖人工验证存在性和安全性;锁定依赖版本(pom.xml / package-lock.json 进 Git);私有仓库代理(Nexus / Artifactory)做统一入口;CI 跑依赖漏洞扫描。
-
AI 时代密钥管理有什么新挑战? AI 可能把硬编码密钥写进代码(从训练数据学来的习惯);开发者可能把密钥喂给 AI 调试(泄露给模型服务商);AI 生成的配置文件示例可能包含真实凭证。对策:密钥扫描进 CI、AI 使用规范明确禁止喂凭证、密钥管理服务统一管控。
自测三问
- AI 生成代码的三大安全风险是什么?各举一个例子。
- 为什么「让 AI 审查自己的代码」不能替代人工审查?
- 自动化安全扫描的三件套(SAST、依赖检查、密钥扫描)分别防什么?
小结一句话
AI 生成代码的安全审查要显性化、清单化、自动化——AI 不知道什么是安全的,你必须知道。
延伸
- OWASP Top 10
- OWASP Dependency-Check
- gitleaks 密钥扫描
- 至此完成全部 12 课,回到第一课:Vibe Coding 是什么