name: afrexai-code-reviewer description: 企业级代码审查智能体。审查PR、差异或代码文件中的安全漏洞、性能问题、错误处理缺失、架构异味和测试覆盖率。适用于任何语言、任何代码库,无需依赖项。 auto_trigger: false
代码审查引擎
企业级自动化代码审查。适用于GitHub PR、本地差异、粘贴的代码或整个文件。无依赖项——纯粹的智能体能力。
快速开始
审查GitHub PR
审查 owner/repo 中的PR #42
审查本地差异
审查此代码库中暂存的更改
审查文件
审查 src/auth/login.ts 的安全问题
审查粘贴的代码
直接粘贴代码并说“审查这个”
审查框架:SPEAR
每次审查都遵循 SPEAR 框架——5个维度,每个维度评分1-10:
🔴 S — 安全性 (权重: 3x)
| 检查项 | 严重性 | 示例 |
|---|---|---|
| 硬编码密钥 | 严重 | 源代码中的API密钥、密码、令牌 |
| SQL注入 | 严重 | 查询中的字符串拼接 |
| XSS向量 | 高 | HTML/DOM中未经处理的用户输入 |
| 路径遍历 | 高 | 文件路径中的用户输入未经验证 |
| 不安全的反序列化 | 高 | 对不可信输入使用 eval()、pickle.loads()、JSON.parse |
| 身份验证绕过 | 严重 | 端点缺少身份验证检查 |
| SSRF | 高 | 服务器请求中使用用户控制的URL |
| 时序攻击 | 中 | 密钥的非恒定时间字符串比较 |
| 依赖项漏洞 | 中 | 导入包中存在已知CVE |
| 敏感数据日志记录 | 中 | 日志输出中包含PII、令牌、密码 |
| 不安全的随机数 | 中 | 对安全敏感值使用 Math.random() |
| 缺少速率限制 | 中 | 身份验证端点未限制频率 |
🟡 P — 性能 (权重: 2x)
| 检查项 | 严重性 | 示例 |
|---|---|---|
| N+1查询 | 高 | 循环内的数据库调用 |
| 无限制查询 | 高 | 面向用户的端点上使用 SELECT * 无LIMIT |
| 缺少索引(隐含) | 中 | 频繁对未索引列进行WHERE/ORDER操作 |
| 内存泄漏 | 高 | 事件监听器未移除、缓存不断增长 |
| 阻塞主线程 | 高 | 异步上下文中的同步I/O、事件循环中的CPU密集型操作 |
| 不必要的重新渲染 | 中 | React:缺少memo、依赖项中的不稳定引用 |
| 大型包导入 | 中 | import _ from 'lodash' 对比 import get from 'lodash/get' |
| 缺少分页 | 中 | 将所有记录返回给客户端 |
| 冗余计算 | 低 | 重复进行相同的昂贵计算而未缓存 |
| 连接池耗尽 | 高 | 未释放数据库/HTTP连接 |
🟠 E — 错误处理 (权重: 2x)
| 检查项 | 严重性 | 示例 |
|---|---|---|
| 吞没错误 | 高 | 空的catch块、Go中 _ := 处理错误 |
| 缺少错误边界 | 中 | React组件缺少错误边界 |
| 未检查null/undefined | 高 | 访问属性前未进行null检查 |
| 缺少finally/清理 | 中 | 打开的资源未保证关闭 |
| 通用错误消息 | 低 | catch(e) { throw new Error("出错了") } |
| 缺少重试逻辑 | 中 | 网络调用未对暂时性故障进行重试 |
| 库代码中的panic/exit | 高 | 非主代码中使用 panic()、os.Exit()、process.exit() |
| 未处理的Promise拒绝 | 高 | 异步调用缺少 .catch() 或 try/catch |
| 错误类型混淆 | 中 | 所有错误同等对待(4xx vs 5xx、可重试 vs 致命) |
🔵 A — 架构 (权重: 1.5x)
| 检查项 | 严重性 | 示例 |
|---|---|---|
| 上帝函数 (>50行) | 中 | 单个函数做太多事情 |
| 上帝文件 (>300行) | 中 | 庞大的模块 |
| 紧耦合 | 中 | 请求处理程序中的直接数据库调用 |
| 缺少抽象 | 低 | 应提取的重复模式 |
| 循环依赖 | 高 | A导入B,B导入A |
| 错误的层级 | 中 | 控制器中的业务逻辑、UI中的SQL |
| 魔法数字/字符串 | 低 | 硬编码值没有命名常量 |
| 缺少类型 | 中 | TypeScript中的 any、Python中缺少类型提示 |
| 死代码 | 低 | 不可达分支、未使用的导入/变量 |
| 不一致的模式 | 低 | 同一代码库中不同的错误处理风格 |
📊 R — 可靠性 (权重: 1.5x)
| 检查项 | 严重性 | 示例 |
|---|---|---|
| 对更改缺少测试 | 高 | 新逻辑没有对应的测试 |
| 测试质量 | 中 | 只检查正常路径的测试 |
| 缺少边界情况 | 中 | 未处理空数组、null、边界值 |
| 竞态条件 | 高 | 共享可变状态未同步 |
| 非幂等操作 | 中 | 重试可能导致重复 |
| 缺少验证 | 高 | 未经验证就接受用户输入 |
| 脆弱的测试 | 低 | 依赖于执行顺序或时间的测试 |
| 缺少日志记录 | 中 | 错误路径没有可观测性 |
| 配置漂移 | 中 | 硬编码的环境特定值 |
| 缺少迁移 | 高 | 模式更改没有迁移文件 |
评分系统
每个发现的严重性
严重 → 维度分数扣3分
高 → 扣2分
中 → 扣1分
低 → 扣0.5分
信息 → 0分(仅建议)
总体SPEAR分数计算
原始分数 = (S×3 + P×2 + E×2 + A×1.5 + R×1.5) / 10
最终分数 = 原始分数 × 10 (0-100分制)
判定阈值
| 分数 | 判定 | 行动 |
|---|---|---|
| 90-100 | ✅ 优秀 | 发布 |
| 75-89 | 🟢 良好 | 微小建议,批准 |
| 60-74 | 🟡 需要改进 | 合并前解决发现的问题 |
| 40-59 | 🟠 重大问题 | 需要重大重构 |
| 0-39 | 🔴 阻止 | 关键问题,不要合并 |
审查输出模板
每次审查都使用此结构:
# 代码审查:[PR标题或文件名]
## 摘要
[1-2句话概述此代码的功能和整体质量]
## SPEAR分数:[X]/100 — [判定]
| 维度 | 分数 | 关键发现 |
|-----------|-------|-------------|
| 🔴 安全性 | X/10 | [最严重发现或“干净”] |
| 🟡 性能 | X/10 | [最严重发现或“干净”] |
| 🟠 错误处理 | X/10 | [最严重发现或“干净”] |
| 🔵 架构 | X/10 | [最严重发现或“干净”] |
| 📊 可靠性 | X/10 | [最严重发现或“干净”] |
## 发现
### [严重/高] 🔴 [标题]
**文件:** `path/to/file.ts:42`
**类别:** 安全性
**问题:** [哪里错了]
**影响:** [可能发生什么]
**修复:**
```[语言]
// 建议的修复
[中] 🟡 [标题]
…
做得好的地方
- [值得指出的真正好的模式]
建议
- [优先处理的事项]
---
## 语言特定模式
### TypeScript / JavaScript
- `any` 类型使用 → 架构发现
- `as` 类型断言 → 潜在运行时错误
- 生产代码中的 `console.log` → 风格
- 使用 `==` 而不是 `===` → 可靠性
- 缺少 `async/await` 错误处理
- `useEffect` 缺少清理返回
- 没有验证的索引签名
### Python
- 裸 `except:` 或 `except Exception:` → 错误处理
- `eval()` / `exec()` → 安全性 严重
- 可变默认参数 → 可靠性
- `import *` → 架构
- 缺少 `__init__.py` 类型提示
- 包含用户输入的f-strings → 潜在注入
### Go
- `_ :=` 丢弃错误 → 错误处理 高
- 库代码中的 `panic()` → 可靠性 高
- 缺少 `defer` 进行资源清理
- 导出的函数没有文档注释
- 过度使用 `interface{}` / `any`
### Java
- 捕获 `Exception` 或 `Throwable` → 错误处理
- 缺少 `@Override` 注解
- 可变静态字段 → 线程安全
- 生产环境中的 `System.out.println`
- 缺少null检查(Optional之前的代码)
### SQL
- 查询中的字符串拼接 → 安全性 严重
- `SELECT *` → 性能
- UPDATE/DELETE缺少WHERE → 安全性 严重
- 面向用户的查询无LIMIT → 性能
- JOIN列缺少索引
---
## 高级技术
### 审查业务逻辑
除了代码质量,检查:
- 代码是否符合PR描述/工单要求?
- 规范中未提及的边界情况?
- 这会破坏现有功能吗?
- 是否有更简单的方法实现相同结果?
### 审查可操作性
- 可以在生产环境中调试吗?(日志记录、错误消息)
- 可以安全回滚吗?
- 需要功能标志吗?
- 此更改应伴随哪些监控?
### 审查数据库更改
- 迁移可逆吗?
- 迁移期间会锁表吗?
- 新查询模式有索引吗?
- 需要数据回填吗?
### 安全审查深度级别
| 级别 | 何时使用 | 审查内容 |
|-------|------|------|
| 快速 | 内部工具,可信输入 | 仅OWASP Top 10模式 |
| 标准 | 面向用户的功能 | + 身份验证、输入验证、输出编码 |
| 深度 | 支付、身份验证、PII处理 | + 加密审查、会话管理、审计日志 |
| 威胁建模 | 新服务/API接口 | + 攻击面映射、信任边界 |
---
## 集成模式
### GitHub PR审查
```bash
# 获取PR差异
gh pr diff 42 --repo owner/repo
# 获取PR详情
gh pr view 42 --repo owner/repo --json title,body,files,commits
# 发布审查评论
gh pr review 42 --repo owner/repo --comment --body "审查内容"
本地Git审查
# 审查暂存的更改
git diff --cached
# 审查分支与main的差异
git diff main..HEAD
# 审查最后N次提交
git log -5 --oneline && git diff HEAD~5..HEAD
心跳/定时任务集成
检查 [repo] 中我尚未审查的开放PR。
对每个PR运行SPEAR审查,并将结果作为PR评论发布。
边界情况和陷阱
- 大型PR (>500行): 拆分为逻辑块。按文件审查。将PR大小本身标记为发现(架构:“PR太大——考虑拆分”)。
- 生成的代码: 跳过生成的文件(proto、swagger、ORM生成的迁移)。注明跳过了它们。
- 依赖项更新: 专注于变更日志中的破坏性更改,而不是lockfile差异。
- 合并冲突标记: 立即标记为严重——代码中的
<<<<<<<意味着合并失败。 - 二进制文件: 注明存在,无法审查内容。
- 配置更改: 额外审查——错误的env变量 = 生产环境中断。
- 重构: 验证行为保留。检查测试在概念上是否仍然通过。
审查清单(快速模式)
当不需要完整SPEAR时的快速审查:
- [ ] 没有硬编码的密钥或凭据
- [ ] 没有SQL注入/XSS/路径遍历
- [ ] 所有错误都已处理(没有空的catch,没有丢弃的错误)
- [ ] 没有N+1查询或无限制操作
- [ ] 新的/更改的逻辑有测试
- [ ] 没有遗留的
console.log/print/fmt.Print - [ ] 函数少于50行,文件少于300行
- [ ] 类型是具体的(没有
any/interface{}) - [ ] PR描述与实际更改相符
- [ ] 没有未链接问题的TODOs