Files
zclaw_openfang/docs/audit-2026-03-30.md
iven eb956d0dce
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
feat: 新增管理后台前端项目及安全加固
refactor(saas): 重构认证中间件与限流策略
- 登录限流调整为5次/分钟/IP
- 注册限流调整为3次/小时/IP
- GET请求不计入限流

fix(saas): 修复调度器时间戳处理
- 使用NOW()替代文本时间戳
- 兼容TEXT和TIMESTAMPTZ列类型

feat(saas): 实现环境变量插值
- 支持${ENV_VAR}语法解析
- 数据库密码支持环境变量注入

chore: 新增前端管理界面
- 基于React+Ant Design Pro
- 包含路由守卫/错误边界
- 对接58个API端点

docs: 更新安全加固文档
- 新增密钥管理规范
- 记录P0安全项审计结果
- 补充TLS终止说明

test: 完善配置解析单元测试
- 新增环境变量插值测试用例
2026-03-31 00:11:33 +08:00

310 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW 全面项目审计报告
> **审计日期**: 2026-03-30
> **审计范围**: 系统架构、代码质量、性能、安全、业务功能、用户体验
> **审计基准**: v0.7.0,基于 F16/S2/S4/S8 完成后的代码状态
> **审计方法**: 5 个并行子代理 + 直接代码分析
---
## 一、执行摘要
### 总体评级: **B+ (良好)**
| 维度 | 评级 | 关键发现 |
|------|------|----------|
| 系统架构 | A- | 10 Crate 分层清晰SaaS 独立feature gate 全覆盖 |
| 代码质量 | B | 0 编译警告453 测试但多文件超限53 处 Promise\<any\> |
| 安全性 | B | Cookie 已实现SQL 全参数化,但登出未撤 token无 TLS |
| 性能 | B | 连接池健康检查完备,但 SSE 不响应 shutdown表无自动清理 |
| 业务功能 | A- | 93 API9 Hands66 Skills前后端对齐SaaS 定时任务执行未闭环 |
### 关键数字
| 指标 | 数值 |
|------|------|
| Rust 代码行数 | 54,380 |
| SaaS API 端点 | 93 (10 模块) |
| Tauri 命令 | 106 |
| 测试数量 | 453 (254 unit + 199 async) |
| Hands | 9 |
| Skills | 66 SKILL.md |
| Pipeline YAML | 7 |
| 编译警告 | 0 (项目自有) |
| TypeScript 错误 | 0 |
---
## 二、系统架构审计
### 2.1 Crate 分层 ✅
```
L1: zclaw-types (无 zclaw 依赖) ✅
L1.5: zclaw-growth (仅依赖 types) — 目录在 L5 但依赖在 L1
L2: zclaw-memory (→ types)
L3: zclaw-runtime (→ types, memory, growth)
L4: zclaw-kernel (→ types, memory, runtime, protocols, hands, skills)
L5: zclaw-skills (→ types), zclaw-hands (→ types, runtime), zclaw-protocols (→ types)
zclaw-pipeline (→ types, runtime, kernel, skills, hands)
独立: zclaw-saas (仅依赖 zclaw-types) ✅
```
**架构代理验证结果**:
- ✅ 无循环依赖DAG
- ✅ SaaS 独立于 Kernel
- ✅ workspace members 完整
- ✅ multi-agent feature 传播链正确: desktop → kernel → protocols/a2a
- ✅ wasm feature gate 完整
- ✅ dev-server feature gate 完整
- `zclaw-growth` 目录位置与依赖层级不一致(不影响功能)
- `zclaw-pipeline` 声明了 `zclaw-kernel` 依赖但代码中未直接 import
### 2.2 数据流完整性 ✅
| 链路 | 状态 | 覆盖 |
|------|------|------|
| Desktop UI → Store → Tauri → Kernel → LLM/Hands/Skills | ✅ 完整 | 106 个 Tauri 命令 |
| Admin V2 → Axios → SaaS API → PostgreSQL | ✅ 完整 | 12 个 service 文件 |
| Pipeline YAML → Executor → LLM/Skill/Hand Actions | ✅ 完整 | 三种 Action driver 均已接通 |
---
## 三、代码质量审计
### 3.1 编译状态 ✅
- `cargo check --workspace`: **0 项目警告**
- `admin-v2 tsc --noEmit`: **通过**
- `desktop tsc --noEmit`: **通过**
### 3.2 大文件审计 ⚠️
**Rust 文件(>800 行)**:
| 文件 | 行数 | 建议 |
|------|------|------|
| `kernel_commands.rs` | **2185** | 按功能域拆分 |
| `lib.rs` (desktop) | **1518** | 命令定义独立 |
| `kernel.rs` | **1490** | 拆分 a2a/scheduler 子模块 |
| `pipeline_commands.rs` | **1391** | 按 stage 拆分 |
| `generation.rs` | 1080 | 逻辑连贯,可保持 |
| `quiz.rs` | 1027 | 题目模板导致 |
| `openai.rs` | 912 | 拆分 streaming 子模块 |
| `director.rs` | 912 | 拆分 turn/submission |
| `loop_runner.rs` | 896 | 拆分 tool execution |
| `store.rs` | 804 | 拆分 query builder |
**TypeScript 文件(>800 行)**:
| 文件 | 行数 | 类型安全 |
|------|------|----------|
| `intelligence-client.ts` | 1471 | 低风险 |
| `kernel-client.ts` | 1343 | 低风险 |
| `saas-client.ts` | 1290 | 低风险 |
| **`gateway-client.ts`** | **1227** | **53 处 Promise\<any\>** |
| **`gateway-api.ts`** | **672** | **同上** |
### 3.3 unwrap() 使用 ⚠️
- 68 个 Rust 文件含 unwrap(),生产代码约 108 处
- `store.rs` 独占 75 处(最高风险)
- **P0 风险**: `extraction_adapter.rs:306-310` 链式 unwrapLLM 返回异常格式时 panic
- **P1 风险**: `context_builder.rs` 多处 HashMap `get_mut().unwrap()`
### 3.4 TypeScript 类型安全
- 0 处 `@ts-ignore` / `@ts-nocheck`
- **53 处 `Promise<any>`** 在 gateway-client.ts + gateway-api.ts最大类型安全盲区
- 6 处静默 `catch(() => {})`saasStore.ts 3 处应添加日志)
- 33 处 `#[allow(dead_code)]`(半数标注 "reserved",需定期审视)
### 3.5 测试覆盖
| Crate | 测试数 | 评价 |
|-------|--------|------|
| zclaw-saas | 111 | 良好 |
| zclaw-growth | 75 | 良好 |
| zclaw-pipeline | 59 | 良好 |
| zclaw-types | 57 | 良好 |
| zclaw-runtime | 42 | 中等 |
| zclaw-kernel | 41 | 需提升 |
| zclaw-skills | 22 | 需提升 |
| zclaw-hands | 21 | 需提升 |
| zclaw-memory | 20 | 需提升 |
| zclaw-protocols | **5** | **不足** |
---
## 四、安全审计
### 4.1 安全发现汇总
| 级别 | ID | 问题 | 文件 |
|------|-----|------|------|
| HIGH | SEC-02 | `saas-config.toml` 含明文 DB 密码 | saas-config.toml:16 |
| HIGH | SEC-03 | ShellSkill SKILL.md 命令注入信任模型 | skills/runner.rs:125 |
| HIGH | SEC-04 | 服务端无 TLS 终止 | saas/main.rs:72 |
| HIGH | SEC-05 | JWT debug fallback 密钥硬编码 | saas/config.rs:238 |
| MED | SEC-06 | 登出未撤销服务端 refresh token | saas/auth/handlers.rs:506 |
| MED | SEC-07 | 注册端点无验证码/邀请机制 | saas/auth/handlers.rs:54 |
| MED | SEC-08 | 角色权限缓存无 TTL/失效 | saas/auth/handlers.rs:397 |
| MED | SEC-09 | 登录缺少专门暴力破解保护 | saas/auth/handlers.rs:160 |
| MED | SEC-10 | 生产 CORS 配置含 localhost | saas-config.toml:12 |
| MED | SEC-11 | Cookie Secure 在非 HTTPS 环境失效 | saas/auth/handlers.rs:29 |
| MED | SEC-13 | TOTP 加密密钥从 JWT Secret 派生 | saas/config.rs:285 |
| LOW | SEC-14 | PythonSkill 脚本路径信任模型 | skills/runner.rs:83 |
| LOW | SEC-15 | Rate limit 信任 X-Forwarded-For | saas/middleware.rs:109 |
### 4.2 安全优势
| 项目 | 状态 |
|------|------|
| SQL 注入防护 | ✅ 100% 参数化0 字符串拼接 |
| 密码哈希 | ✅ Argon2id + spawn_blocking |
| Refresh Token Rotation | ✅ 一次性使用 + SHA-256 hash 存储 |
| API Key 加密 | ✅ AES-256-GCM + 随机 nonce |
| 错误信息处理 | ✅ 500 不泄露内部细节 |
| 审计日志 | ✅ 覆盖所有关键操作 + IP |
| TOTP 暴力破解保护 | ✅ 5 次失败锁定 10 分钟 |
| XSS 防护 | ✅ 唯一 innerHTML 用 DOMPurify |
| 账号隔离 | ✅ 所有查询强制 account_id |
| CORS 安全 | ✅ 生产强制白名单 |
---
## 五、性能审计
### 5.1 严重性能问题
| 问题 | 影响 | 文件 |
|------|------|------|
| SSE 流不检查 CancellationToken | graceful shutdown 等待最长 5 分钟 | relay/service.rs |
| 数据表无自动清理 | operation_logs/usage_records/relay_tasks 无限增长 | scheduler.rs |
| 连接池偏小 (max=20) | 高并发 SSE 场景不足 | db.rs:12 |
| Scheduler 循环不监听 shutdown token | 后台 task 不会被取消 | scheduler.rs:55,78,111 |
### 5.2 中等性能问题
| 问题 | 文件 |
|------|------|
| relay_tasks 缺 (account_id, status) 复合索引 | relay/handlers.rs:31 |
| SSE usage 跳过后 task 永久 "processing" | relay/service.rs:302 |
| OTA 提示词 N+1 查询(每模板 2 次) | prompt/service.rs:242 |
| totp_fail_counts 无清理机制 | state.rs:26 |
| `operation_logs` COUNT(*) 无时间范围 | account/handlers.rs:144 |
### 5.3 性能优势
| 项目 | 设计 |
|------|------|
| 连接池健康检查 | 80% 水位 503 + 3s 超时 |
| TCP keepalive | 60s/10s/3次 + SO_LINGER 1s |
| SSE 背压 | bounded channel(128) |
| SSE 并发限制 | Semaphore(16) |
| DashMap 死锁 | RefMut 在 await 前释放 |
| 前端无轮询 | TanStack Query 按需触发 |
---
## 六、业务功能审计
### 6.1 SaaS API 完整度 ✅
| 模块 | 端点数 | CRUD |
|------|--------|------|
| auth (含 TOTP) | 9 | 完整认证流程 |
| account (含 tokens/devices/logs/stats) | 12 | ✅ |
| provider | 6 | ✅ C/R/U/D |
| model | 5 | ✅ C/R/U/D |
| api_keys (含 rotate) | 5 | ✅ |
| relay (含 key pool) | 9 | ✅ |
| config/migration | 12 | ✅ + sync/diff/pull |
| role + permission_template | 11 | ✅ |
| prompt (含 versions/rollback) | 10 | ✅ |
| agent_template | 5 | ✅ |
| scheduled_task | 5 | ✅ |
| telemetry | 4 | ✅ |
| health | 1 | ✅ |
| **总计** | **93** | **完整** |
### 6.2 前后端对齐 ✅
- Admin V2: 12 个 service 文件 → 后端路由全部匹配
- baseURL `/api/v1` + Vite proxy → 无断链
- `withCredentials: true` → Cookie 自动发送
- **后端就绪但无 Admin UI**: Role 管理、TOTP、Prompt 版本、定时任务管理
### 6.3 功能缺口
| 功能 | 后端 | 前端 Admin | 状态 |
|------|------|-----------|------|
| Role CRUD | ✅ 4 端点 | ❌ | 后端就绪 |
| Permission Template | ✅ 4 端点 | ❌ | 后端就绪 |
| TOTP 2FA | ✅ 3 端点 | ❌ | 后端就绪 |
| Prompt 版本管理 | ✅ 4 端点 | ❌ | 后端就绪 |
| 定时任务管理 | ✅ 5 端点 | ❌ | 后端就绪 |
| SaaS 定时任务执行 | ⚠️ 仅状态管理 | — | **未闭环** |
| Kernel 定时任务执行 | ✅ TriggerManager | ✅ | 完整闭环 |
### 6.4 Approval 流程 ✅
完整闭环: 触发 → 检查 → 创建审批 → 前端通知 → 审批/拒绝 → 执行 → 结果通知
---
## 七、待改进项(按优先级)
### P0 — 必须修复
| ID | 问题 | 影响 |
|----|------|------|
| P0-1 | SSE 流不检查 CancellationToken | 停机等待最长 5 分钟 |
| P0-2 | 数据表无自动清理 (logs/usage/relay_tasks) | 磁盘耗尽 + 查询退化 |
| P0-3 | `store.rs` 75 处 unwrap | 数据库异常导致 panic |
| P0-4 | `extraction_adapter.rs` 链式 unwrap | LLM 异常输出导致 panic |
| P0-5 | 登出未撤销服务端 refresh token | XSS 后 token 仍可用 |
### P1 — 应该修复
| ID | 问题 | 影响 |
|----|------|------|
| P1-1 | `kernel_commands.rs` 2185 行 | 可维护性 |
| P1-2 | `gateway-client.ts` 53 处 Promise\<any\> | 类型安全盲区 |
| P1-3 | 连接池 max=20 偏小 | 高并发不足 |
| P1-4 | relay_tasks 缺复合索引 | 查询性能 |
| P1-5 | Scheduler 循环不响应 shutdown | 优雅停机不完整 |
| P1-6 | `saas-config.toml` 含明文密码 | 安全风险 |
| P1-7 | Cookie Secure 在 localhost 失效 | 开发环境认证失败 |
| P1-8 | 登录缺暴力破解保护 | 安全风险 |
| P1-9 | `zclaw-protocols` 仅 5 个测试 | 回归风险 |
### P2 — 可以改进
| ID | 问题 | 影响 |
|----|------|------|
| P2-1 | 多个文件 >800 行 | 代码组织 |
| P2-2 | 角色权限缓存无失效机制 | 降权不即时生效 |
| P2-3 | `sqlx-postgres 0.7.4` 未来兼容性 | 编译噪音 |
| P2-4 | SaaS 定时任务执行未闭环 | 功能不完整 |
| P2-5 | `scheduled_tasks` 路径缺 `/v1` 前缀 | API 一致性 |
| P2-6 | OTA 提示词 N+1 查询 | 性能 |
---
## 八、架构优势
1. **SaaS 独立部署** — 不依赖 Kernel可独立扩展
2. **Feature gate 分离** — multi-agent 功能可选
3. **Cookie + Header 双路径认证** — 向后兼容 + 安全
4. **声明式 Scheduler** — TOML 配置驱动
5. **参数化 SQL 全覆盖** — 零注入风险
6. **连接池健康检查** — 80% 水位自动降级
7. **Argon2id 密码哈希** — 业界最佳实践
8. **审计日志全覆盖** — 所有关键操作 + IP
9. **SSE 背压设计** — bounded channel 防内存溢出
---
*审计完成。5 个并行子代理深度审计,覆盖架构/代码/安全/性能/业务全维度。*