714 lines
22 KiB
Markdown
714 lines
22 KiB
Markdown
|
|
# IT智能服务台 — 风险跟踪表
|
|||
|
|
|
|||
|
|
**最后更新**: 2026-06-14 18:30
|
|||
|
|
**维护人**: 宋献 + Claude 评审协作
|
|||
|
|
|
|||
|
|
> 📌 2026-06-14 评审新增 13 项(6 P0 + 4 P1 + 3 P2),详见第九节。
|
|||
|
|
> 统计表保持 6-13 数据,**第九节有独立小计**。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、风险总览
|
|||
|
|
|
|||
|
|
| 级别 | 数量 | 已处理 | 待处理 | 处理率 |
|
|||
|
|
|------|------|--------|--------|--------|
|
|||
|
|
| 🔴 严重 (Critical) | 4 | 4 | 0 | **100%** |
|
|||
|
|
| 🟠 高 (High) | 6 | 5 | 1 | **83%** |
|
|||
|
|
| 🟡 中 (Medium) | 7 | 4 | 3 | **57%** |
|
|||
|
|
| 🔵 低 (Low) | 5 | 3 | 2 | **60%** |
|
|||
|
|
| **合计** | **22** | **16** | **6** | **73%** |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、严重风险 (Critical)
|
|||
|
|
|
|||
|
|
### CR-1:`dependencies.py` 覆盖导致依赖注入链断裂
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已验证(无需修复)
|
|||
|
|
**风险级别**: 🔴 严重
|
|||
|
|
**处理难度**: ⚠️ 高
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
当前的 `dependencies.py` 是完全重写的,可能缺少原始文件中的共享服务依赖注入函数。
|
|||
|
|
|
|||
|
|
**验证结果**:
|
|||
|
|
经检查,当前 `dependencies.py` 文件已包含所有必要的函数:
|
|||
|
|
- `get_redis()` — Redis 连接池管理
|
|||
|
|
- `dep_redis()` — Redis 客户端依赖注入
|
|||
|
|
- `dep_wecom_service()` — 企微服务依赖注入
|
|||
|
|
- `dep_ai_handler()` — AI 处理器依赖注入
|
|||
|
|
- `dep_wingman_service()` — Wingman 服务依赖注入
|
|||
|
|
- `get_shared_redis()` — 同步获取 Redis
|
|||
|
|
- `get_shared_wecom_service()` — 同步获取企微服务
|
|||
|
|
- `get_shared_ai_handler()` — 同步获取 AI 处理器
|
|||
|
|
- `init_shared_services()` — 应用启动初始化
|
|||
|
|
- `cleanup_shared_services()` — 应用关闭清理
|
|||
|
|
|
|||
|
|
**结论**:
|
|||
|
|
文件完整,无需恢复。依赖注入链正常。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### CR-2:Token 格式不兼容导致认证混乱
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🔴 严重
|
|||
|
|
**处理难度**: ⚠️ 中
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
系统存在三种 Token 格式同时运行,可能导致认证混乱。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. `TokenService.get_user_info()` 支持三种格式读取:
|
|||
|
|
- 统一格式:`user:token:{token}` → JSON 对象
|
|||
|
|
- 旧格式1:`employee:token:{token}` → employee_id
|
|||
|
|
- 旧格式2:`agent:token:{token}` → user_id
|
|||
|
|
|
|||
|
|
2. `TokenService.create_token()` 同时写入统一格式和旧格式:
|
|||
|
|
- 根据 `login_source` 决定写入 `employee:token:` 或 `agent:token:`
|
|||
|
|
|
|||
|
|
3. `TokenService.switch_role()` 更新统一格式,旧格式只存储 employee_id 不需要更新
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/services/token_service.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### CR-3:Portal API 使用旧认证中间件
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🔴 严重
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
Portal API 使用 `get_current_agent` 作为认证依赖,不支持新的统一格式。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 修改 `portal.py` 使用 `get_current_user` 替代 `get_current_agent`
|
|||
|
|
2. 修改 `admin_roles.py` 使用 `get_current_user` 替代 `get_current_agent`
|
|||
|
|
3. 更新所有函数签名和参数名(`agent` → `current_user`)
|
|||
|
|
4. 更新所有日志记录(`agent.user_id` → `current_user.employee_id`)
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/api/portal.py`
|
|||
|
|
- `backend/app/api/admin_roles.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### CR-4:慢启动时 Token 创建失败导致登录异常
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🔴 严重
|
|||
|
|
**处理难度**: ⚠️ 中
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
坐席登录时每次创建新的 Redis 连接,并在 finally 中关闭,可能导致连接泄漏。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 使用共享 Redis 连接(从 `get_redis()` 获取)
|
|||
|
|
2. 移除 finally 中的连接关闭代码(由连接池管理)
|
|||
|
|
3. 简化异常处理逻辑
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/api/agents.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、高风险 (High)
|
|||
|
|
|
|||
|
|
### H-6:角色映射 SQL 注入风险
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟠 高
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
`_get_tag_names_by_ids()` 方法直接调用企微 API,没有对返回的 `tag_names` 进行验证。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 添加 `_validate_tag_name()` 方法验证标签名称
|
|||
|
|
2. 验证规则:长度限制 50 字符,过滤禁止的特殊字符
|
|||
|
|
3. 获取标签时过滤不安全的标签名称
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/services/role_mapping_service.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### H-7:角色分配权限验证不完整
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟠 高
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
管理员可以给任何人分配任何角色,包括自己。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 禁止管理员给自己分配角色(assign_role 添加检查)
|
|||
|
|
2. 禁止管理员撤销自己的角色(revoke_role 添加检查)
|
|||
|
|
3. 操作审计日志(通过 logger.info 记录)
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/api/admin_roles.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### H-8:映射规则缺少输入验证
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟠 高
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
`create_mapping_rule()` 接口没有验证输入参数。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 添加 `source_type` 枚举验证(`wecom_tag`/`ehr_position`)
|
|||
|
|
2. 添加 `role_name` 枚举验证(`user`/`agent`/`admin`)
|
|||
|
|
3. 添加 `source_value` 特殊字符过滤
|
|||
|
|
4. 限制 `priority` 范围(0-100)
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/schemas/role.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### H-9:Token 未绑定 IP/设备
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🟠 高
|
|||
|
|
**处理难度**: ⚠️ 中
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
Token 没有绑定 IP 地址或设备指纹,任何获取到 Token 的人都可以使用。
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
1. 绑定 IP 地址(可选,影响移动场景)
|
|||
|
|
2. 绑定设备指纹(可选,需要前端配合)
|
|||
|
|
3. 敏感操作要求二次验证
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- Token 安全加固
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### H-10:管理端 API 无 IP 白名单
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟠 高
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
管理端角色管理 API 没有 IP 白名单限制。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 在 Nginx 层添加 IP 白名单(/itadmin/ 和 /api/admin/ 路径)
|
|||
|
|
2. 允许内网网段:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、10.212.0.0/16
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `deploy-server/nginx/nginx.conf`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### H-11:WebSocket Token 通过 URL 参数传递
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🟠 高
|
|||
|
|
**处理难度**: ⚠️ 中
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
WebSocket 连接的 Token 通过 URL 参数传递,会被记录在访问日志中。
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
1. 改为通过 WebSocket 握手头传递
|
|||
|
|
2. 或通过第一条消息传递
|
|||
|
|
3. 在 Nginx 中对 `/ws/` 路径关闭访问日志
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- WebSocket 安全加固
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、中等风险 (Medium)
|
|||
|
|
|
|||
|
|
### M-6:旧 Token 迁移策略缺失
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 中
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
没有从旧格式迁移到新格式的策略。
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
1. 实现 Token 自动迁移(访问旧格式 Token 时自动转换为新格式)
|
|||
|
|
2. 设置迁移期限(如 30 天后旧 Token 失效)
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- Token 迁移工具
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### M-7:角色缓存策略缺失
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
每次请求都从数据库查询用户角色,没有缓存策略。
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
1. 添加 Redis 缓存(TTL 5-10 分钟)
|
|||
|
|
2. 角色变更时主动失效缓存
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- 角色缓存实现
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### M-8:API 速率限制未覆盖所有端点
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
只覆盖了登录端点,其他 API 端点没有速率限制。
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
1. 为所有 API 端点添加速率限制
|
|||
|
|
2. 分级限制:登录 10/min,普通 API 60/min,管理 API 30/min
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- 速率限制完善
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### M-9:异常信息泄露
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
异常处理返回 `f"服务器内部错误: {str(exc)}"`,可能泄露内部信息。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 异常处理器返回通用错误消息:"服务器内部错误,请稍后重试或联系管理员"
|
|||
|
|
2. 中间件返回通用错误消息(同上)
|
|||
|
|
3. 详细异常信息仅记录到日志
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/main.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### M-10:日志脱敏不足
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
日志中包含 `user_id`、`employee_id` 等敏感信息。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 添加 `_mask_sensitive_data()` 脱敏函数
|
|||
|
|
2. 对 employee_id 进行脱敏处理(保留前3位,如 "abc***def")
|
|||
|
|
3. 已处理:role_mapping_service.py、admin_roles.py
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/services/role_mapping_service.py`
|
|||
|
|
- `backend/app/api/admin_roles.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### M-11:数据库密码弱密码
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
PostgreSQL 密码使用 `wecom_secret` 或 `wecom_secret_2026`,强度不足。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. `.env.example` 中使用强密码占位符(`your-strong-postgres-password`)
|
|||
|
|
2. 添加注释说明密码要求(≥16位,含大小写字母+数字+特殊字符)
|
|||
|
|
3. 生产环境通过 `.env` 文件注入强密码
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `.env.example`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### M-12:Redis 无密码保护
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🟡 中
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
Redis 连接无密码认证。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. Docker Compose 中添加 `--requirepass` 参数
|
|||
|
|
2. `.env.example` 中添加 `REDIS_PASSWORD` 配置项
|
|||
|
|
3. 更新 `REDIS_URL` 格式为 `redis://:password@redis:6379/0`
|
|||
|
|
4. 健康检查使用密码认证
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `deploy-server/docker-compose.yml`
|
|||
|
|
- `.env.example`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、低风险 (Low)
|
|||
|
|
|
|||
|
|
### L-5:Nginx 缺少 CSP 和 HSTS 安全头
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🔵 低
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
在 Nginx 配置中添加以下安全头:
|
|||
|
|
```nginx
|
|||
|
|
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;" always;
|
|||
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|||
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `deploy-server/nginx/nginx.conf`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### L-6:CORS 配置过于宽松
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🔵 低
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
```python
|
|||
|
|
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
|||
|
|
allow_headers=["Authorization", "Content-Type", "X-Employee-Id"],
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/main.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### L-7:坐席列表 API 无认证
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已修复
|
|||
|
|
**风险级别**: 🔵 低
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
**修复日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
坐席列表 API 没有认证保护,任何人都可以访问。
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 导入 `require_role` 依赖
|
|||
|
|
2. 添加 `@require_role("agent", "admin")` 装饰器
|
|||
|
|
|
|||
|
|
**修改文件**:
|
|||
|
|
- `backend/app/api/agents.py`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### L-8:Nginx `client_max_body_size` 过大
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🔵 低
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
```nginx
|
|||
|
|
location /api/upload/ {
|
|||
|
|
client_max_body_size 50m;
|
|||
|
|
}
|
|||
|
|
location /api/ {
|
|||
|
|
client_max_body_size 1m;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- Nginx 配置优化
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### L-9:前端硬编码配置
|
|||
|
|
|
|||
|
|
**状态**: ⚠️ 待处理
|
|||
|
|
**风险级别**: 🔵 低
|
|||
|
|
**处理难度**: ⚠️ 低
|
|||
|
|
**发现日期**: 2026-06-13
|
|||
|
|
|
|||
|
|
**处理建议**:
|
|||
|
|
1. 通过环境变量注入配置
|
|||
|
|
2. 避免在前端代码中硬编码敏感信息
|
|||
|
|
|
|||
|
|
**关联开发任务**:
|
|||
|
|
- 前端配置优化
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、处理计划
|
|||
|
|
|
|||
|
|
### 第一阶段:紧急修复(已完成)
|
|||
|
|
|
|||
|
|
| 序号 | 任务 | 风险项 | 状态 |
|
|||
|
|
|------|------|--------|------|
|
|||
|
|
| 1 | 恢复 `dependencies.py` 并合并新功能 | CR-1 | ✅ 已验证 |
|
|||
|
|
| 2 | 统一 Token 格式并确保向后兼容 | CR-2 | ✅ 已修复 |
|
|||
|
|
| 3 | 修改 Portal API 使用新认证中间件 | CR-3 | ✅ 已修复 |
|
|||
|
|
| 4 | 修复坐席登录的 Redis 连接管理 | CR-4 | ✅ 已修复 |
|
|||
|
|
| 5 | 添加角色分配权限验证 | H-7 | ⚠️ 待处理 |
|
|||
|
|
| 6 | 添加映射规则输入验证 | H-8 | ✅ 已修复 |
|
|||
|
|
|
|||
|
|
### 第二阶段:安全加固(上线后 1 周内)
|
|||
|
|
|
|||
|
|
| 序号 | 任务 | 风险项 | 状态 |
|
|||
|
|
|------|------|--------|------|
|
|||
|
|
| 7 | Token 绑定 IP/设备指纹 | H-9 | ⚠️ 待处理 |
|
|||
|
|
| 8 | 管理端 API 添加 IP 白名单 | H-10 | ⚠️ 待处理 |
|
|||
|
|
| 9 | WebSocket Token 改为头传递 | H-11 | ⚠️ 待处理 |
|
|||
|
|
| 10 | 实现旧 Token 迁移策略 | M-6 | ⚠️ 待处理 |
|
|||
|
|
| 11 | 添加角色缓存 | M-7 | ⚠️ 待处理 |
|
|||
|
|
| 12 | 为所有 API 添加速率限制 | M-8 | ⚠️ 待处理 |
|
|||
|
|
|
|||
|
|
### 第三阶段:纵深防御(上线后 2 周内)
|
|||
|
|
|
|||
|
|
| 序号 | 任务 | 风险项 | 状态 |
|
|||
|
|
|------|------|--------|------|
|
|||
|
|
| 13 | 异常处理不再泄露内部信息 | M-9 | ⚠️ 待处理 |
|
|||
|
|
| 14 | 日志脱敏处理 | M-10 | ⚠️ 待处理 |
|
|||
|
|
| 15 | PostgreSQL 更换强密码 | M-11 | ⚠️ 待处理 |
|
|||
|
|
| 16 | Redis 设置密码 | M-12 | ⚠️ 待处理 |
|
|||
|
|
| 17 | Nginx 添加 CSP/HSTS 安全头 | L-5 | ⚠️ 待处理 |
|
|||
|
|
| 18 | 收紧 CORS 配置 | L-6 | ⚠️ 待处理 |
|
|||
|
|
| 19 | 坐席列表 API 添加认证 | L-7 | ⚠️ 待处理 |
|
|||
|
|
| 20 | Nginx 按路径细分文件大小限制 | L-8 | ⚠️ 待处理 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、风险关联开发任务
|
|||
|
|
|
|||
|
|
以下风险与当前开发任务关联,需要在相关任务完成时一并处理:
|
|||
|
|
|
|||
|
|
| 风险项 | 关联开发任务 | 处理时机 |
|
|||
|
|
|--------|--------------|----------|
|
|||
|
|
| H-6 | 角色映射服务开发 | 实现时添加验证 |
|
|||
|
|
| H-7 | 角色管理 API 完善 | 实现时添加权限检查 |
|
|||
|
|
| H-9 | Token 安全加固 | Token 服务完善时 |
|
|||
|
|
| H-10 | 管理端访问控制 | 部署时配置 |
|
|||
|
|
| H-11 | WebSocket 安全加固 | WS 重构时 |
|
|||
|
|
| M-6 | Token 迁移工具 | 上线前 |
|
|||
|
|
| M-7 | 角色缓存实现 | 性能优化时 |
|
|||
|
|
| M-8 | 速率限制完善 | 安全加固时 |
|
|||
|
|
| M-9 | 异常处理优化 | 代码审查时 |
|
|||
|
|
| M-10 | 日志脱敏实现 | 日志系统优化时 |
|
|||
|
|
| M-11 | 生产环境配置 | 部署时 |
|
|||
|
|
| M-12 | 生产环境配置 | 部署时 |
|
|||
|
|
| L-5~L-9 | Nginx/前端优化 | 部署/优化时 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、维护说明
|
|||
|
|
|
|||
|
|
1. **定期审查**:每月审查一次风险状态,更新处理进度
|
|||
|
|
2. **新风险录入**:发现新风险时及时录入本表
|
|||
|
|
3. **关联开发任务**:开发任务涉及风险项目时,与风险项目一并处理并更新状态
|
|||
|
|
4. **状态更新**:风险处理完成后,更新状态为 ✅ 已修复,并记录修复日期
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、2026-06-14 workbuddy 推送评审新增
|
|||
|
|
|
|||
|
|
**评审依据**: `docs/评审报告/workbuddy-2026-06-14-消息优化.md`
|
|||
|
|
**评审范围**: workbuddy 6-14 推送 + `IT智能服务台-版本更新说明-20250614.md`
|
|||
|
|
**小计**: 13 项发现(6 P0 + 4 P1 + 3 P2),其中 7 项已修本地代码,6 项待 workbuddy 跟进
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 9.1 🔴 严重 (新增 6 项,**全部已修**)
|
|||
|
|
|
|||
|
|
#### CR-5:H5 participants 端点无会话参与权限校验 → P0-1
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复(2026-06-14 本地代码)
|
|||
|
|
- **风险级别**: 🔴 严重(数据泄露)
|
|||
|
|
- **位置**: `backend/app/api/h5.py:1107-1145`
|
|||
|
|
- **问题**: 仅校验"用户已登录",未校验"是否属于本会话",任意已登录员工可枚举 conversation_id 读取他会话参与者
|
|||
|
|
- **修复**: 加 is_creator / is_participant 双重校验
|
|||
|
|
|
|||
|
|
#### CR-6:recall_message 端点无鉴权 → P0-2
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复
|
|||
|
|
- **风险级别**: 🔴 严重(数据破坏)
|
|||
|
|
- **位置**: `backend/app/api/messages.py:293-340`
|
|||
|
|
- **问题**: 端点签名只有 `db: AsyncSession = Depends(get_db)`,**无任何鉴权依赖**
|
|||
|
|
- **修复**: 加 `agent: Agent = Depends(get_current_agent)` + `message.sender_id == agent.user_id` 校验
|
|||
|
|
|
|||
|
|
#### CR-7:delete_message 端点无鉴权 → P0-3
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复
|
|||
|
|
- **位置**: `backend/app/api/messages.py:336-365`
|
|||
|
|
- **修复**: 同 CR-6
|
|||
|
|
|
|||
|
|
#### CR-8:mark_read 端点无鉴权 + 会话访问未校验 → P0-4
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复
|
|||
|
|
- **位置**: `backend/app/api/messages.py:368-405`
|
|||
|
|
- **问题**: 任意人可调用改任意会话已读状态,破坏"未读数"业务
|
|||
|
|
- **修复**: 加 agent 鉴权 + `assigned_agent_id` / `collaborating_agent_ids` 校验
|
|||
|
|
- **捎带修**: `where(Message.is_read == False)` 改为 `is_(False)`(P2-1,原表达式在 SQLAlchemy 静默失效)
|
|||
|
|
|
|||
|
|
#### CR-9:upload_image 端点无鉴权 → P0-5
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复
|
|||
|
|
- **位置**: `backend/app/api/messages.py:400-462`
|
|||
|
|
- **问题**: 任意 HTTP 客户端可上传图片占用磁盘(无大小硬限、无频率限制)
|
|||
|
|
- **修复**: 加 `Depends(get_current_agent)`
|
|||
|
|
|
|||
|
|
#### CR-10:upload_message_file 端点无鉴权 → P0-6
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复
|
|||
|
|
- **位置**: `backend/app/api/messages.py:458-525`
|
|||
|
|
- **修复**: 同 CR-9
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 9.2 🟠 高 (新增 4 项,**全部待 workbuddy 跟进**)
|
|||
|
|
|
|||
|
|
#### H-12:upload 路径在容器本地,容器重建即丢失 → P1-1
|
|||
|
|
|
|||
|
|
- **状态**: ⚠️ 待处理
|
|||
|
|
- **风险级别**: 🟠 高(数据丢失)
|
|||
|
|
- **位置**: `backend/app/api/messages.py:434,487`
|
|||
|
|
- **问题**: `media/images/` 和 `media/files/` 写容器本地,容器重建或重启丢所有上传
|
|||
|
|
- **处理建议**: 改 volume mount(参考 nginx 静态文件挂载模式,参考 `docker-compose.yml:142-145`)
|
|||
|
|
|
|||
|
|
#### H-13:SQL 迁移未走 Alembic → P1-2
|
|||
|
|
|
|||
|
|
- **状态**: ⚠️ 待处理
|
|||
|
|
- **风险级别**: 🟠 高(schema 漂移)
|
|||
|
|
- **位置**: `alembic/versions/`(缺)、`models/message.py:190-204`
|
|||
|
|
- **问题**: 模型已有 `status` / `recallable_until` 字段,但**未见对应 Alembic 迁移脚本**;版本文档教用户手动 `ALTER TABLE`(反模式)
|
|||
|
|
- **处理建议**: 跑 `alembic revision --autogenerate -m "add message status and recallable_until"` 自动生成迁移
|
|||
|
|
|
|||
|
|
#### H-14:docker-compose backend healthcheck 用 curl → P1-3
|
|||
|
|
|
|||
|
|
- **状态**: ⚠️ 待处理
|
|||
|
|
- **风险级别**: 🟠 高(监控失真)
|
|||
|
|
- **位置**: `docker-compose.yml:117-122`
|
|||
|
|
- **问题**: `curl -f http://localhost:8000/health || exit 1`,**backend 精简 Python 镜像无 curl** → healthcheck 永远 unhealthy
|
|||
|
|
- **关联记忆**: [[backend-healthcheck-curl-pitfall]]
|
|||
|
|
- **处理建议**: 改用 `python -c "import socket; s=socket.socket(); s.connect(('localhost',8000))"`(Python 镜像必有)
|
|||
|
|
|
|||
|
|
#### H-15:ws_manager 文档承诺"消息状态广播"未实现 → P1-4
|
|||
|
|
|
|||
|
|
- **状态**: ⚠️ 待处理
|
|||
|
|
- **风险级别**: 🟠 高(文档与代码不符)
|
|||
|
|
- **位置**: `docs/IT智能服务台-版本更新说明-20250614.md:46` 声称改动 / `backend/app/services/ws_manager.py` 实际无对应方法
|
|||
|
|
- **问题**: ConnectionManager 仅有 `send_to_agent` / `broadcast` / `send_to_employee` / `broadcast_to_employees`,**无 `broadcast_message_status(conv_id, msg_id, status)`**
|
|||
|
|
- **处理建议**: 实现该方法 + WebSocket 消息格式
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 9.3 🟡 中 (新增 3 项,1 已修,2 待跟进)
|
|||
|
|
|
|||
|
|
#### M-13:upload 写文件非原子 → P2-2
|
|||
|
|
|
|||
|
|
- **状态**: ⚠️ 待处理
|
|||
|
|
- **位置**: `backend/app/api/messages.py:440,494`
|
|||
|
|
- **问题**: `with open(file_path, "wb") as f: f.write(content)`,中途崩溃留半文件
|
|||
|
|
- **处理建议**: 先写 `*.tmp` 再 `os.rename` 原子化
|
|||
|
|
|
|||
|
|
#### M-14:upload 返回原始文件名 → P2-3
|
|||
|
|
|
|||
|
|
- **状态**: ⚠️ 待处理
|
|||
|
|
- **位置**: `backend/app/api/messages.py:501`
|
|||
|
|
- **问题**: `"filename": original_name` 返回原始文件名,可能含中文 / 特殊字符(XSS 风险)
|
|||
|
|
- **处理建议**: URL encode 或服务端做白名单过滤
|
|||
|
|
|
|||
|
|
#### M-15:mark_read SQL `== False` 表达式静默失效 → P2-1
|
|||
|
|
|
|||
|
|
- **状态**: ✅ 已修复(捎带在 P0-4 修复中)
|
|||
|
|
- **位置**: `backend/app/api/messages.py:388`(原)
|
|||
|
|
- **问题**: `where(Message.is_read == False)` 在 SQLAlchemy 中不报错但**实际未生效**(Python `==` 返回 False → SQLAlchemy 当赋值处理但参数已绑死)
|
|||
|
|
- **修复**: 改为 `is_(False)`,走 SQL `is false` 否定
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 9.4 文档本身的 4 处错误(已记录待修订)
|
|||
|
|
|
|||
|
|
| # | 位置 | 错误 | 建议修订 |
|
|||
|
|
|---|------|------|----------|
|
|||
|
|
| D-1 | 版本说明部署步骤 5 | `docker compose -p root up -d` **正是用户 6-14 生产事故的根因** | **删除 `-p root` 标志** |
|
|||
|
|
| D-2 | 版本说明部署步骤 6 | SQL `DEFAULT 'sent'` 引号未转义(shell 语法错) | 改用 Alembic 迁移脚本 |
|
|||
|
|
| D-3 | 版本说明 2.1 ws_manager | 声称"添加消息状态广播"但实际未实现 | 改"规划中"或"本次未实现" |
|
|||
|
|
| D-4 | 版本说明 2.1 docker-compose | "healthcheck 已配置"不准确 | 加注 backend curl 坑 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 9.5 评审结论与流程建议
|
|||
|
|
|
|||
|
|
- **P0 比例 46% (6/13) 过高** —— workbuddy 后续推送需**强制走评审流程**
|
|||
|
|
- **建议加 pre-commit 检查**: 新增端点无 `Depends(...)` 鉴权依赖时拒绝推送
|
|||
|
|
- **下次推送窗口**: 等 H-12~15 + M-13/14 全部修完再合入,**不在评审未消化前叠加新功能**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 9.6 新增项状态速查
|
|||
|
|
|
|||
|
|
| 编号 | 状态 | 编号 | 状态 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| CR-5 (P0-1) | ✅ | H-12 (P1-1) | ⚠️ |
|
|||
|
|
| CR-6 (P0-2) | ✅ | H-13 (P1-2) | ⚠️ |
|
|||
|
|
| CR-7 (P0-3) | ✅ | H-14 (P1-3) | ⚠️ |
|
|||
|
|
| CR-8 (P0-4) | ✅ | H-15 (P1-4) | ⚠️ |
|
|||
|
|
| CR-9 (P0-5) | ✅ | M-13 (P2-2) | ⚠️ |
|
|||
|
|
| CR-10 (P0-6) | ✅ | M-14 (P2-3) | ⚠️ |
|
|||
|
|
| | | M-15 (P2-1) | ✅(捎带)|
|