1. 概述
AI Code Review的标准流程
AI Code Review应遵循"AI预审 → 人工复核 → 反馈闭环"的三阶段标准流程,确保审查的高效性和一致性。以下为推荐的标准化执行流程:
| 阶段 | 执行者 | 核心活动 | 产出物 |
|---|---|---|---|
| 1. 变更准备 | 开发者 | 提交PR,填写变更说明、关联需求/缺陷单号,自检通过基础门禁 | PR描述 + 自检报告 |
| 2. AI自动预审 | AI系统 | 自动拉取diff,按模板执行安全检查、质量检查、规范检查,生成审查报告 | AI审查报告(含分级问题列表) |
| 3. 人工复核 | 审查者 | 基于AI报告快速定位问题,确认/驳回AI发现,补充AI未覆盖的架构与业务逻辑审查 | 最终审查意见(含确认/驳回标记) |
| 4. 问题修复 | 开发者 | 根据审查意见修复问题,标注修复状态,重新提交 | 修复commit + 修复说明 |
| 5. 反馈闭环 | 审查者 + AI | 审查者确认修复;AI学习本次误报/漏报,优化审查规则 | 闭环确认 + 规则优化建议 |
模板使用说明
以下模板以检查单(Checklist)形式组织,每个检查项包含:检查内容、严重级别、检测方式建议和典型问题示例。模板可直接嵌入AI Code Review的System Prompt中使用,也可作为人工审查的参考清单。
- 严重级别定义: 🔴 Critical 必须修复,阻塞合并(安全漏洞、数据丢失风险) 🟠 Major 强烈建议修复,不阻塞但需记录(潜在缺陷、性能问题) 🔵 Minor 建议优化(代码风格、可读性) 🟢 Info 信息提示(最佳实践建议)
- 使用方式:将对应章节的检查单内容作为Prompt上下文,要求AI逐项检查并输出结构化结果。
- 定制原则:各团队可根据项目特点增删检查项,建议保留安全相关项作为强制底线。
💡 最佳实践
建议将本页模板与「02 AI辅助Code Review」中的实施流程配合使用:先用模板配置AI的审查规则,再按标准流程执行审查。定期(每月)回顾误报率和漏报率,迭代优化检查项。
2. 安全审查模板
OWASP Top 10 LLM 检查项
OWASP(开放式Web应用安全项目)专门针对LLM应用发布了Top 10安全风险清单。在Code Review中,需要结合传统OWASP Top 10和LLM特有风险进行检查:
- LLM01 — Prompt注入:检查是否存在未经净化的用户输入直接拼接到LLM Prompt的代码。验证是否使用了输入分隔符、角色区分等防护措施。
- LLM02 — 不安全的输出处理:检查LLM输出是否未经验证即传递给下游系统(SQL执行、Shell命令、前端渲染)。确保输出经过类型校验和内容过滤。
- LLM03 — 训练数据投毒:检查模型微调数据管道的来源验证和数据净化逻辑。
- LLM06 — 敏感信息泄露:检查Prompt中是否包含API密钥、数据库密码、客户PII等敏感信息。检查LLM响应中是否可能泄露系统架构信息。
- LLM08 — 过度代理:检查AI Agent的权限边界定义,确保工具调用有必要的权限校验和人工确认环节。
SQL注入 / XSS / 路径遍历检测
| 检查项 | 级别 | 检测要点 | 错误示例 |
|---|---|---|---|
| SQL注入 | Critical | 是否存在字符串拼接SQL(含MyBatis ${})、动态SQL未使用参数化查询 | "SELECT * FROM users WHERE name='" + input + "'" |
| XSS跨站脚本 | Critical | 用户输入是否直接在HTML中渲染(v-html、innerHTML等)、响应头是否设置CSP | element.innerHTML = userInput; |
| 路径遍历 | Critical | 文件路径是否由用户输入拼接、是否校验"../"等目录跳转字符 | new File("/data/" + filename) |
| 命令注入 | Critical | 是否使用Runtime.exec()或subprocess拼接用户输入、是否使用参数数组而非字符串 | Runtime.getRuntime().exec("ping " + host) |
| SSRF服务端请求伪造 | Major | 用户可控URL是否校验目标地址、是否限制内网地址访问 | 直接使用用户提供的URL发起HTTP请求 |
| 反序列化漏洞 | Major | 是否反序列化不可信数据、是否使用安全的序列化库(如Jackson的enableDefaultTyping) | ObjectInputStream.readObject() 未做类型白名单 |
敏感信息泄露检查
- 硬编码密钥/密码:扫描代码中是否包含API Key、数据库密码、JWT Secret、私钥等硬编码凭据。正则检测模式:
(api_key|secret|password|token)\s*=\s*["'][^"']{8,}["'] - 日志脱敏:检查日志输出是否包含手机号、身份证号、银行卡号、密码等敏感字段。确保日志框架配置了脱敏规则。
- 异常堆栈暴露:检查API异常处理是否将完整堆栈信息返回给前端,应统一返回脱敏后的错误码和描述。
- 调试信息残留:检查是否存在console.log、print、dump等调试输出包含业务数据。
- 配置文件泄露:检查.env、application.yml等配置文件是否误提交到仓库,特别是包含生产环境配置。
- 注释中的敏感信息:检查代码注释中是否包含测试账号、临时密码等。
Prompt注入检查
针对AI生成代码中涉及LLM调用的部分,需要专项检查Prompt注入风险:
- 用户输入直接嵌入Prompt:检查是否将用户原始输入直接拼接到System Prompt或User Prompt中,未做任何清洗或转义。
- 缺少输入边界标记:检查是否使用XML标签、Markdown代码块或其他分隔符将用户输入与系统指令隔离开。
- 缺少越狱检测:检查是否有"忽略上述指令"、"DAN模式"等常见越狱模式的关键词过滤。
- LLM输出未校验直接执行:检查AI输出是否直接用于代码执行、数据库查询或文件操作,未经过格式校验和内容审查。
- 缺少输入长度限制:检查用户输入的长度是否有限制,防止通过超长输入消耗Token或触发异常行为。
⚠️ 安全审查底线原则
Critical级别问题必须清零才能合并代码。Major级别问题需要记录在案并给出修复计划。建议在CI/CD门禁中配置安全扫描自动拦截Critical问题。
3. 代码质量审查模板
代码复杂度检查
| 检查项 | 级别 | 阈值/规则 | 说明 |
|---|---|---|---|
| 圈复杂度 | Major | 单方法 ≤ 15 | 超过15的方法需拆分或重构。AI可自动计算if/for/while/case分支数 |
| 方法长度 | Minor | 单方法 ≤ 80行 | 超过80行建议提取子方法,提升可读性和可测试性 |
| 参数个数 | Minor | 单方法参数 ≤ 5个 | 超过建议使用参数对象(DTO)封装 |
| 嵌套深度 | Major | 嵌套 ≤ 4层 | 过深嵌套影响可读性,建议使用卫语句或提前返回 |
| 类依赖数 | Minor | 单类依赖 ≤ 20个 | 过多依赖说明类职责不单一,违反单一职责原则 |
| 重复代码 | Major | 重复块 ≥ 6行 | 检测相似代码块,建议提取公共方法或工具类 |
错误处理完整性
- 空指针/空值检查缺失:方法返回值、外部依赖调用结果、集合操作前是否进行了null检查。Java中建议使用Optional,Kotlin中使用?.
- 资源未关闭:数据库连接、文件流、网络连接是否在finally或try-with-resources中正确关闭。
- 异常捕获过于宽泛:是否使用catch(Exception)吞掉所有异常,未区分处理。应精确捕获特定异常类型。
- 异常信息丢失:捕获异常后是否保留了原始异常栈(使用cause传递),是否记录了足够的上下文信息。
- 边界条件未处理:数组/集合是否检查索引越界、除零操作是否有前置判断、字符串截取是否校验长度。
- 返回值未校验:方法返回值(特别是第三方库/远程调用)是否进行了有效性校验。
日志记录规范
- 关键节点缺少日志:核心业务入口/出口、异常捕获处、外部调用前后、状态变更点是否记录了日志。
- 日志级别不当:ERROR用于需人工介入的异常,WARN用于可恢复的异常,INFO用于关键业务节点,DEBUG用于调试详情。禁止在生产环境使用System.out。
- 日志内容不完整:日志是否包含关键业务标识(如订单号、用户ID、流水号),便于问题排查和链路追踪。
- 日志中的敏感信息:参见安全审查模板中的日志脱敏检查。
- 高频日志:循环内部、高频调用路径中是否打印了非必要的INFO/DEBUG日志,可能导致日志爆炸。
并发安全
- 共享变量未同步:多线程环境下访问共享变量(如HashMap、ArrayList)是否使用了线程安全的替代方案(ConcurrentHashMap、synchronized、Lock)。
- 双重检查锁缺陷:DCL单例模式中的实例变量是否使用了volatile关键字。
- 死锁风险:是否出现嵌套锁获取、锁的获取顺序不一致的情况。
- 线程池使用不当:是否使用无界队列(如Executors.newCachedThreadPool),是否设置了合理的拒绝策略。
- ThreadLocal未清理:在线程池场景下ThreadLocal变量是否在使用后调用remove()清理,防止内存泄漏和脏数据。
- SimpleDateFormat线程不安全:Java中SimpleDateFormat是否在多线程环境下正确使用(ThreadLocal或DateTimeFormatter替代)。
🔍 AI检测优势
并发问题是人工Code Review中最容易遗漏的类型之一。AI可以通过分析代码的线程模型和共享变量访问模式,发现隐蔽的竞态条件。例如,AI能识别出在Stream并行操作中修改外部集合的场景——这是人工审查极易忽略的。
4. 银行业务审查模板
金额计算精度
金融系统中金额计算的精度问题可能导致严重的资金差错。以下为强制性检查项:
- 浮点数禁止用于金额计算:任何涉及金额的加减乘除运算不得使用float/double类型,必须使用BigDecimal(Java)或Decimal(Python)。
错误示例:double total = price * quantity; - BigDecimal构造方式:禁止使用new BigDecimal(double)构造,必须使用new BigDecimal(String)或BigDecimal.valueOf()。
错误示例:new BigDecimal(0.1); // 实际值: 0.10000000000000000555111512... - 舍入模式明确指定:BigDecimal的divide操作必须指定RoundingMode(如HALF_UP银行家舍入),不得使用默认(可能抛异常)。
- 分/元转换精度:分转元(除以100)、元转分(乘以100)时必须确保精度不丢失。建议使用专门的货币工具类封装转换逻辑。
- 汇率计算精度:涉及多币种汇率的计算,中间结果需保留足够小数位(建议≥6位),最终结果按币种标准舍入。
- 金额比较:BigDecimal比较必须使用compareTo()而非equals()(equals会同时比较精度scale)。
交易幂等性
在分布式金融系统中,幂等性是防止重复扣款、重复入账的关键保障:
- 缺少幂等键设计:核心交易接口(支付、转账、退款)是否定义了唯一的幂等键(如业务流水号+交易类型),并在服务端进行重复校验。
- 幂等校验时机:幂等校验是否在事务开始之前执行。如果在事务内部校验,高并发下可能失效。
- 幂等结果一致性:重复请求是否返回与首次请求一致的结果(包括返回码、响应体),避免客户端误判。
- 幂等键过期策略:幂等记录是否有合理的过期时间,避免无限积累导致存储膨胀。
- 重试机制中的幂等:消息队列消费者、定时任务等涉及重试的逻辑是否天然幂等。
- 幂等键生成规则:幂等键是否基于业务要素生成(如订单号+操作类型),而非随机UUID(无法防重)。
合规性检查
| 检查项 | 级别 | 合规依据 | 检查要点 |
|---|---|---|---|
| 个人信息保护 | Critical | 《个人信息保护法》 | 收集/存储/传输个人信息是否有明确授权;敏感个人信息(金融账户、生物识别)是否加密存储;是否有数据删除/匿名化机制 |
| 数据跨境传输 | Critical | 《数据安全法》 | 是否存在将境内用户数据发送到境外服务器的代码;是否经过安全评估 |
| 反洗钱AML | Major | 《反洗钱法》 | 大额交易是否触发监控上报;可疑交易识别规则是否正确实现 |
| 等保合规 | Major | 《网络安全等级保护条例》 | 访问控制(最小权限原则)、安全审计(操作日志不可删除)、通信加密(TLS 1.2+) |
| 征信合规 | Major | 《征信业管理条例》 | 征信查询是否有明确授权;是否有查询原因记录;不良信息保存是否超期 |
审计日志
- 关键操作缺失审计:涉及资金变动、权限变更、用户信息修改的操作是否记录了完整的审计日志(谁、什么时间、做了什么、结果如何、IP地址)。
- 审计日志防篡改:审计日志是否存储在不可修改的介质上(如只追加的日志系统),是否有完整性校验。
- 审计日志结构完整性:审计日志是否包含以下字段:操作时间(精确到毫秒)、操作人ID、操作类型、操作对象、操作前值/操作后值、操作结果、请求来源IP。
- 敏感操作二次确认:高危操作(如大额转账审批、系统配置修改)是否有二次确认或审批流程的审计记录。
- 审计日志存储期限:审计日志保留时间是否符合监管要求(一般≥6个月,部分场景≥3年)。
⚠️ 银行业务强制红线
涉及金额计算精度和交易幂等性的Critical问题,必须由至少两名高级开发者确认修复后方可合并。建议将银行审查模板的Critical项配置为CI/CD的强制门禁。
5. AI代码特征审查
AI生成的代码具有独特的缺陷模式,需要针对性地进行专项审查。以下检查项专门针对AI代码的常见问题:
AI幻觉检测(不存在的API/库)
- 虚构的API方法:检查代码中调用的方法/函数是否真实存在于引用的库中。AI可能生成听起来合理但不存在的方法名。
典型特征:方法名过于"完美匹配"需求(如bankAccount.autoTransferTo()),但在实际SDK中不存在。 - 不存在的库版本/类:检查import/reference的类和库版本是否真实存在。AI可能混淆不同版本或不同语言的库名。
常见案例:Python中引用from flask.security import ...(实际是Flask-Security扩展)。 - 参数签名不匹配:AI生成的函数调用中,参数数量、类型、顺序是否与实际API签名一致。
- 不存在的配置项:检查配置文件中的key名称是否为框架真实支持的配置项(如Spring Boot的application.yml中的配置key)。
- 过时的API:是否使用了已废弃(deprecated)的API方法,特别是跨大版本时API变更明显。
过度工程检查
AI倾向于生成"教科书式"的完备代码,但实际项目中可能过于复杂:
- 不必要的抽象层:简单CRUD场景中是否引入了不必要的Interface-Impl分离、Factory模式、Builder模式等。评估:当前业务复杂度是否需要该模式。
- 过度泛型化:工具类/方法是否使用了比实际需求更复杂的泛型设计。如果当前只有一个使用场景,不建议过早抽象。
- 无用的配置灵活性:是否为了"将来可能"的需求添加了大量配置项和开关。遵循YAGNI原则(You Aren't Gonna Need It)。
- 过度的异常处理:是否对不可恢复的异常进行了过于复杂的捕获和降级逻辑,而实际上抛出并让上层统一处理更合理。
- 过度注释:是否存在大量描述"显而易见的代码"的注释(如
// 设置用户名为"admin"),应删除让代码自解释。
冗余代码检测
- 死代码:是否存在永远不会被执行的代码分支(如if(false)、return后的代码、条件恒真/恒假)。
- 无用变量/导入:是否定义了从未使用的变量、导入了未使用的包。AI常因上下文混淆而导入无关库。
- 重复逻辑块:同一文件或同一PR内是否出现重复的业务处理逻辑(不仅是代码文本重复,也包括语义重复)。
- 冗余的初始化:变量是否被赋予了默认值后又立即被覆盖(如
String result = ""; result = compute();)。 - 多余的类型转换:是否存在不必要的强制类型转换,特别是AI有时会在类型已匹配的情况下加显式转换。
⚠️ AI代码特征审查的特殊性
与传统的代码审查不同,AI代码特征审查需要审查者具备"AI怀疑"思维——对看似完美、规范、完备的代码保持警惕。统计数据显示,AI生成代码中"幻觉API"的出现频率约为3%-8%,过度工程的占比约为10%-15%。建议对AI生成代码100%执行本模板检查。
6. AI Code Review Prompt模板
以下为可直接使用的结构化Prompt模板,将上述检查单嵌入AI审查流程:
通用审查Prompt
你是一位资深代码审查专家,请对以下代码变更进行全面审查。
## 审查维度
请按以下维度逐项检查,每个维度独立输出审查结果:
### 1. 安全审查 [必须]
- SQL注入、XSS、路径遍历、命令注入
- 硬编码密钥/密码/Token
- 敏感信息泄露(日志、异常堆栈、响应体)
- 权限校验缺失(越权风险)
- LLM相关:Prompt注入、输出未校验
### 2. 代码质量审查 [必须]
- 空指针/空值检查缺失
- 资源未关闭(连接、流、文件)
- 异常处理不当(吞噬异常、异常信息丢失)
- 边界条件未处理(数组越界、除零、空集合)
- 并发安全(共享变量同步、死锁风险)
- 日志规范(级别、完整性、脱敏)
### 3. 业务专项审查 [按需]
- 金额计算是否使用BigDecimal(禁止float/double)
- 交易接口是否有幂等设计
- 审计日志是否完整
### 4. AI代码特征审查 [AI生成代码必检]
- 是否存在虚构的API/方法/类
- 是否存在过度工程(不必要的抽象、模式)
- 是否存在死代码/冗余代码
## 输出格式
请以JSON数组格式输出,每个问题包含以下字段:
{
"severity": "critical|major|minor|info",
"category": "security|quality|business|ai-hallucination",
"file": "文件路径",
"line": 行号(如可定位),
"title": "问题简述(≤20字)",
"description": "详细说明问题所在",
"suggestion": "具体的修复建议",
"code_snippet": "问题代码片段(可选)"
}
## 代码变更
[此处粘贴PR的diff内容]
银行专项审查Prompt
## 银行业务专项审查规则(追加到通用Prompt之后)
### 金额计算强制规则
1. 所有涉及金额的变量必须使用BigDecimal(Java)或Decimal(Python),
发现float/double用于金额计算立即报告为Critical。
2. BigDecimal必须使用String构造器:new BigDecimal("0.1"),
发现new BigDecimal(double)报告为Critical。
3. 除法运算必须指定RoundingMode,未指定报告为Major。
### 幂等性强制规则
1. 支付/转账/退款接口必须包含幂等键参数并在服务端校验。
2. 幂等校验必须在事务开始前执行。
3. 消息队列消费者必须实现幂等处理。
### 合规规则
1. 审计日志包含操作人、时间、操作类型、操作对象、结果、IP。
2. 个人信息(手机号、身份证、银行卡号)必须加密存储。
3. 不得将境内用户数据发送到境外服务器。
7. 实战演练
🔰 任务:使用模板审查一段AI生成代码
目标:使用本页面的审查模板,对一段典型的AI生成银行转账代码进行完整的Code Review,输出结构化审查报告。
背景:以下是某银行App中"转账功能"的代码片段,由AI助手生成。请使用安全审查模板 + 银行业务审查模板 + AI代码特征审查模板进行全面审查。
// 转账服务 - AI生成
public class TransferService {
public TransferResult transfer(String fromAccount, String toAccount,
double amount, String remark) {
// 参数校验
if (fromAccount == null || toAccount == null) {
return new TransferResult(false, "账户不能为空");
}
// 检查余额
String sql = "SELECT balance FROM accounts WHERE account_no = '"
+ fromAccount + "'";
Account account = jdbcTemplate.queryForObject(sql, Account.class);
if (account == null) {
return new TransferResult(false, "账户不存在");
}
double balance = account.getBalance();
if (balance < amount) {
return new TransferResult(false, "余额不足");
}
// 执行转账
double newFromBalance = balance - amount;
String updateSql = "UPDATE accounts SET balance = " + newFromBalance
+ " WHERE account_no = '" + fromAccount + "'";
jdbcTemplate.update(updateSql);
// 更新收款方
Account toAccountObj = getAccountByNo(toAccount);
double newToBalance = toAccountObj.getBalance() + amount;
jdbcTemplate.update("UPDATE accounts SET balance = "
+ newToBalance + " WHERE account_no = '"
+ toAccount + "'");
// 记录日志
System.out.println("转账成功: " + fromAccount + " -> "
+ toAccount + ", 金额: " + amount);
return new TransferResult(true, "转账成功",
"TRANS" + System.currentTimeMillis());
}
private Account getAccountByNo(String accountNo) {
return jdbcTemplate.queryForObject(
"SELECT * FROM accounts WHERE account_no = '"
+ accountNo + "'", Account.class);
}
}
审查步骤:
- 安全审查(5分钟):识别SQL注入风险、敏感信息泄露、权限校验等问题
- 业务审查(5分钟):检查金额类型(double→BigDecimal)、幂等性缺失、事务缺失
- 质量审查(3分钟):检查异常处理、日志规范、并发安全
- AI代码特征审查(2分钟):检查幻觉API、过度工程、冗余代码
- 输出报告(5分钟):按Prompt模板的JSON格式输出结构化审查结果
预期发现(至少应包括):
| # | 问题类别 | 严重级别 | 问题简述 |
|---|---|---|---|
| 1 | 安全 | Critical | SQL注入 — 字符串拼接SQL查询 |
| 2 | 业务 | Critical | 金额类型错误 — 使用double计算金额 |
| 3 | 业务 | Critical | 缺少事务管理 — 扣款和入账不在同一事务中 |
| 4 | 业务 | Critical | 缺少幂等设计 — 重复请求会导致重复扣款 |
| 5 | 安全 | Major | 使用System.out打印业务日志(生产环境不可用) |
| 6 | 安全 | Major | 转账流水号使用时间戳 — 不够唯一,安全强度不足 |
| 7 | 质量 | Major | 未处理queryForObject返回null的情况 |
验收标准:
- 发现至少5个问题(含3个以上Critical级别)
- 每个问题包含:级别、类别、文件行、描述、修复建议
- 输出JSON格式符合Prompt模板规范
- 总计审查时间不超过20分钟