代码审查清单
在合并前让 Agent 按安全、性能、可测性维度逐项检查 diff;本页把「作者 → 审查者 → 合并」串成可执行阶段,并给出严重度矩阵与可筛选的注释示例。
将审查维度拆成可勾选项:注入与鉴权、敏感数据、错误处理、边界用例、测试覆盖与破坏性变更说明。Agent 可按文件类型与 diff 规模调整优先级;建议在 SKILL 中写明「不通过则拒绝合并」的硬性条件,以及「需人工确认」的灰色项。
对大型 PR,可先输出「变更摘要 + 风险等级」再逐项清单;对仅文档或配置变更,可收缩安全项、保留格式与链接有效性检查。与 CI 对齐,避免清单与流水线门禁脱节。
审查流程(作者 → 审查者 → 合并)
三阶段职责边界清晰时,Agent 不易把「该作者补的测试」与「该审查者拍板的架构」混为一谈。下列流程适用于人类协作;若由 Agent 代行审查,应显式标注当前角色(author / reviewer / merge-gate)。
[ 作者:自测、说明、可审查的最小 diff ]
│
▼
[ 审查者:通读描述 → 看 diff → 打标 P0/P1/P2 ]
│
┌─────────┴─────────┐
▼ ▼
[ 阻塞:须修订 ] [ 非阻塞:可合并前跟 ]
│ │
└─────────┬─────────┘
▼
[ 合并:CI 绿、保护分支规则、(可选)第二人审批 ]
│
▼
[ 合并后:监控 / 回滚预案 ]
展开:作者阶段交付物
自检清单勾选、PR 描述含动机与风险、关联 issue、截图或 API 契约变更说明;超大变更先拆 PR 或附「阅读地图」。
可直接复制的 PR 描述模板:
## 变更动机 ## 影响范围 ## 测试方案 - [ ] 单测(新增/修改了哪些用例) - [ ] 集成/E2E(可选,说明覆盖场景) - [ ] 手动验证步骤(截图/录屏可附) ## 回滚步骤 1. revert commit: `git revert` 2. 若有数据库迁移:执行 `make db-rollback` ## 截图 / Trace(可选)
展开:审查者阶段要点
先读描述再读代码;每条意见带严重度与可操作结论;P0 必须阻断合并;对猜测性意见标为 nit 或 P2,避免噪音淹没真正的安全问题。
展开:合并门禁
分支保护、必需审查人数、状态检查(CI、签名提交)、以及团队约定的「无未解决 P0」规则;Agent 代合并前须复述这些条件是否满足。
严重度矩阵与定义
团队可对 SLA 微调;关键是合并策略与 P0/P1 语义在全仓库一致。
| 级别 | 典型含义 | 合并策略 | 处理期望(示例) |
|---|---|---|---|
| P0 | 安全/合规/数据损坏/生产必崩 | 禁止合并,须修复或回滚变更 | 当日或随 hotfix 窗口 |
| P1 | 明显逻辑错误、缺失关键测试、错误处理缺口 | 默认阻塞;极个别可在 issue 跟踪下例外(需记录) | 本迭代内 |
| P2 | 风格、命名、小优化、文档笔误 | 不阻塞;可 follow-up | 排期或 good first issue |
- P0
- 合并会导致 exploit、越权、明文密钥上线,或确定性崩溃路径。
- P1
- 损害正确性、可观测性或回滚能力;缺测试覆盖的关键分支。
- P2
- 可读性与一致性;不影响正确性与安全性的建议。
10 条必须阻塞合并的红线(含具体代码模式)
🔴 1. 硬编码凭证
const apiKey = "sk-prod-abc123"; // ← 明文 secret 进代码库
🔴 2. 绕过鉴权(路由 / 中间件层被注释掉或 if 恒真)
// router.use(authMiddleware); // ← 鉴权中间件被注释
🔴 3. 用户输入直接拼 SQL
`SELECT * FROM users WHERE id = ${req.params.id}` // SQL 注入
🔴 4. 可反序列化入口无类型/schema 校验
const body = JSON.parse(rawInput); // 没有 Zod/Joi/yup 校验直接使用
🔴 5. 日志打印敏感字段
logger.info("用户登录", { password, token }); // 密码/token 进日志
🔴 6. IDOR:资源 ID 来自客户端且未校验所属关系
const order = await Order.findById(req.body.orderId); // 没有 .userId 校验
🔴 7. 删除或跳过关键测试(覆盖率人为置高)
it.skip("退款并发测试", ...) // ← 为了覆盖率绿跳过关键测试
🔴 8. 数据库字段删除未走扩张—收缩(直接 DROP COLUMN)
ALTER TABLE orders DROP COLUMN legacy_status; // 无迁移回滚路径
🔴 9. 无界递归或无限循环进主流程
function retry(fn) { return retry(fn); } // ← 无终止条件递归
🔴 10. 生产环境标志被强制设为 debug/开发模式
NODE_ENV=development # 写死在生产 Dockerfile 或 k8s configmap
按 P0 / P1 筛选注释(示意)
下方为静态示例列表,点击标签可筛选严重度,便于对照 SKILL 中「输出结构化审查意见」的格式。与编排页的勾选进度不同,本页侧重注释分级展示。
维度检查表
Agent 可按 diff 类型裁剪;下列为常见列,可映射到自动化规则或人工速查。
| 维度 | 检查要点 | 不通过时倾向 |
|---|---|---|
| 安全 | 鉴权、注入、敏感日志、依赖 CVE、密钥与配置落盘 | P0 / P1 |
| 正确性 | 边界、并发、幂等、与契约/迁移一致性 | P0 / P1 |
| 性能 | 热路径、N+1、大对象、无界缓存 | 多为 P1,极端为 P0 |
| 可测性 | 关键分支测试、可 mock 边界、flake 风险 | 通常 P1 |
| 可运维 | 日志字段、指标、功能开关、回滚路径 | P1 / P2 |
SKILL 片段
将阶段与严重度写进 SKILL,便于模型稳定输出结构化审查结果。
---
name: code-review-checklist
description: 在合并前对 PR diff 执行分层安全与质量审查,输出结构化意见
---
# 角色声明(每次审查前先明确当前扮演的角色)
当前角色: reviewer # 可选: author | reviewer | merge-gate
# 第一步:读 PR 描述(2 分钟)
- 确认变更动机是否清晰;若无 PR 描述,要求作者先补全再继续
- 检查是否标注了影响范围(破坏性变更 / 数据库迁移 / API 变更)
- 确认回滚步骤存在且可操作
# 第二步:安全扫描(必须阻塞红线)
- [ ] 无硬编码凭证/密钥/token(grep: `sk-`, `password =`, `secret =`)
- [ ] 用户输入未直接拼 SQL / 命令行 / HTML(检查所有 `${req.*}` 注入点)
- [ ] 鉴权中间件未被注释/绕过(检查路由层)
- [ ] 日志无敏感字段(password、token、ssn、card_number)
- [ ] IDOR:资源 ID 必须经过所属权校验
# 第三步:正确性(P0/P1)
- [ ] 并发路径有无竞态(非原子的 check-then-act)
- [ ] 边界:空值 / 零 / 负数 / 超长 input 是否处理
- [ ] 与 API 契约、数据库 schema、消息格式是否一致
# 第四步:可测性(P1)
- [ ] 新增 happy path 有对应单测
- [ ] 错误分支(网络/DB 超时、业务异常)有测试
- [ ] 关键集成路径有集成测试或 contract test
# 第五步:可运维(P1/P2)
- [ ] 新端点/服务有日志与指标上报
- [ ] 新功能有 Feature Flag(若需灰度)
- [ ] 失败时可回滚(无不可逆副作用)
# 输出格式(必须)
对每条意见输出:
级别: P0 | P1 | P2
文件: 相对路径
行号: L42 (若适用)
问题: 一句话描述问题
建议: 可操作的修复方向或代码片段
新接口未校验 session,且将用户 id 来自客户端参数——须改为服务端会话或签名校验。
退款分支无集成测试;建议在「部分退款 + 并发」场景补一例,避免回归。
环境变量表缺新加的
FEATURE_X说明,可合并后跟文档 PR。错误路径仅打 console.error,未返回统一错误码;与现有 API 规范不一致。
用户 ID 直接拼入 SQL 字符串:
WHERE id = ${req.params.id},必须改用参数化查询WHERE id = $1+ 绑定参数。当前代码可被1; DROP TABLE users--攻击。processRefund()在 catch 块中吞掉了StripeError而仅返回false;调用方无法区分「网络超时」与「余额不足」,也没有上报指标。需把错误类型传出或映射为业务错误码。formatCurrency硬编码了'zh-CN'locale;建议改为从调用方传入,便于多语言复用。不阻塞合并,可 follow-up issue 跟踪。