Files
zclaw_openfang/docs/superpowers/specs/2026-03-30-comprehensive-audit-report.md
iven bc8c77e7fe fix(security): P0 审计修复 — 6项关键安全/编译问题
F1: kernel.rs multi-agent 编译错误 — 重排 spawn_agent 中 A2A 注册顺序,
    在 config 被 registry.register() 消费前使用
F2: saas-config.toml 从 git 追踪中移除 — 包含数据库密码已进入版本历史
F3: config.rs 硬编码开发密钥改用 #[cfg(debug_assertions)] 编译时门控 —
    dev fallback 密钥不再进入 release 构建
F4: 公共认证端点添加 IP 速率限制 (20 RPM) — 防止暴力破解
F5: SSE relay 路由分离出全局 15s TimeoutLayer — 避免长流式响应被截断
F6: Provider API 密钥入库前 AES-256-GCM 加密 — 明文存储修复

附带:完整审计报告 docs/superpowers/specs/2026-03-30-comprehensive-audit-report.md
2026-03-30 13:32:22 +08:00

400 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.8.0
**审计范围**: 系统架构、代码质量、性能表现、安全状况、业务功能、用户体验
---
## 执行摘要
### 整体健康评分: 6.5/10
ZCLAW 在快速迭代后展现出坚实的核心架构(清晰的 Crate 分层、零 `unsafe`、零 `todo!()`),但在安全防护、连接管理和前端健壮性方面存在显著缺陷。
| 维度 | 评分 | 关键发现数 |
|------|------|-----------|
| 架构健康度 | 7.5/10 | 15 项 |
| 性能与稳定性 | 5.5/10 | 14 项 |
| 安全审计 | 5.0/10 | 17 项 |
| UX/功能完整性 | 6.5/10 | 12 项 |
| **合计** | | **58 项** |
### 严重级别分布
| 级别 | 数量 | 说明 |
|------|------|------|
| Critical | 6 | 阻塞级,必须立即修复 |
| High | 12 | 高风险,本迭代内修复 |
| Medium | 22 | 中等风险,下迭代修复 |
| Low | 18 | 低风险,纳入待办 |
### 推荐立即行动项
1. **SEC-1**: `saas-config.toml` 含数据库密码且被 Git 追踪 → `git rm --cached`
2. **FEAT-01**: `kernel.rs:444` multi-agent 编译错误 → 修改变量名
3. **RATE-1**: 公共认证端点无速率限制 → 添加限制
4. **CW-1**: 15s TimeoutLayer 中断 SSE 流 → 排除 relay 路由
5. **CRYPTO-1**: Provider API 密钥明文存储在数据库 → 启用加密
6. **UX-01**: Admin V2 无 Error Boundary → 添加全局错误边界
---
## 架构依赖图
```mermaid
graph TD
TYPES[zclaw-types<br/>L0: 基础类型] --> MEMORY[zclaw-memory<br/>L1: 存储层]
TYPES --> GROWTH[zclaw-growth<br/>L1: 成长系统]
TYPES --> SKILLS[zclaw-skills<br/>L2: 技能系统]
TYPES --> PROTOCOLS[zclaw-protocols<br/>L2: 协议支持]
MEMORY --> RUNTIME[zclaw-runtime<br/>L2: 运行时]
GROWTH --> RUNTIME
TYPES --> RUNTIME
RUNTIME --> HANDS[zclaw-hands<br/>L2: 自主能力]
TYPES --> HANDS
RUNTIME --> KERNEL[zclaw-kernel<br/>L3: 核心协调]
MEMORY --> KERNEL
PROTOCOLS --> KERNEL
HANDS --> KERNEL
SKILLS --> KERNEL
TYPES --> PIPELINE[zclaw-pipeline<br/>L2: 工作流]
RUNTIME --> PIPELINE
KERNEL --> PIPELINE
SKILLS --> PIPELINE
HANDS --> PIPELINE
KERNEL --> DESKTOP[desktop/src-tauri<br/>L4: 桌面应用]
SKILLS --> DESKTOP
HANDS --> DESKTOP
PROTOCOLS --> DESKTOP
MEMORY --> DESKTOP
RUNTIME --> DESKTOP
PIPELINE --> DESKTOP
GROWTH --> DESKTOP
TYPES --> SAAS[zclaw-saas<br/>ISO: SaaS 后端]
PIPELINE -.->|向上依赖<br/>违规| KERNEL
DESKTOP -.->|绕过抽象层<br/>直接依赖| MEMORY
DESKTOP -.->|绕过抽象层| RUNTIME
style PIPELINE fill:#fff3cd
style DESKTOP fill:#fff3cd
```
**图例**: 黄色节点表示存在架构违规
---
## 维度 1架构健康度
### 1.1 Crate 分层合规性
**整体评价**: 层次清晰,无循环依赖,但存在 2 处违规。
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| LAYER-01 | `zclaw-pipeline`(L2) 向上依赖 `zclaw-kernel`(L3) | High | `crates/zclaw-pipeline/Cargo.toml:28` |
| LAYER-02 | `zclaw-hands``zclaw-runtime` 同层互相依赖 | Medium | `crates/zclaw-hands/Cargo.toml:12` |
| LAYER-03 | `desktop/src-tauri` 直接导入 L1/L2 crate 绕过 kernel 抽象 | Medium | `desktop/src-tauri/Cargo.toml:28-34` |
### 1.2 依赖一致性
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| LAYER-04 | `serde_yaml = "0.9"` 已弃用 | Low | `crates/zclaw-pipeline/Cargo.toml:15` |
| LAYER-05 | zclaw-saas 6 个依赖未使用 workspace 声明 | Low | `crates/zclaw-saas/Cargo.toml:44-48` |
### 1.3 中间件链
6 个中间件按优先级顺序正确执行100-700无遗漏。
| 优先级 | 中间件 | 状态 |
|--------|--------|------|
| 100 | CompactionMiddleware | 错误传播可能中断链 (MW-03) |
| 150 | MemoryMiddleware | 非致命错误处理正确 |
| 200 | SkillIndexMiddleware | 正常 |
| 400 | GuardrailMiddleware | 正常 |
| 500 | LoopGuardMiddleware | 正常 |
| 700 | TokenCalibrationMiddleware | 正常 |
### 1.4 Feature Gate 安全
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| **FEAT-01** | `kernel.rs:444` `config_clone` 未定义multi-agent 编译失败 | **Critical** | `crates/zclaw-kernel/src/kernel.rs:444` |
| FEAT-04 | 无 CI 步骤验证 feature gate 编译 | Low | CI 配置 |
### 1.5 代码组织
**超过 1000 行的文件**(硬限制违规):
| 文件 | 行数 | 建议 |
|------|------|------|
| `kernel.rs` | 1,453 | 拆分为 agent/hands/triggers/approvals/skills 子模块 |
| `generation.rs` | 1,080 | 提取工具调用逻辑 |
| `quiz.rs` | 1,027 | 提取评分逻辑 |
| `intelligence-client.ts` | 1,471 | 按域拆分 |
| `kernel-client.ts` | 1,353 | 按域拆分 |
| `gateway-client.ts` | 1,227 | 按域拆分 |
| `saas-client.ts` | 1,213 | 按域拆分 |
---
## 维度 2性能与稳定性
### 2.1 CLOSE_WAIT 修复验证
**当前状态**: 部分修复,存在关键冲突。
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| **CW-1** | 全局 15s TimeoutLayer 会中断 SSE relay 流 | **Critical** | `crates/zclaw-saas/src/main.rs:187` |
| **CW-2** | 客户端断开时上游请求不取消,保持 300s | **Critical** | `crates/zclaw-saas/src/relay/service.rs:252-294` |
| CW-3 | PG 连接在客户端断开后仍被延迟写入任务持有 | Medium | `crates/zclaw-saas/src/relay/service.rs:301-317` |
| CW-6 | Admin 代理 30s 超时对 SSE 流不够 | Medium | `admin-v2/vite.config.ts:18-19` |
### 2.2 连接池行为
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| CP-1 | Key pool 选择每请求最多 11 次顺序 DB 查询 | High | `crates/zclaw-saas/src/relay/key_pool.rs:43-141` |
| CP-3 | 无熔断器,池耗尽时级联失败 | High | `crates/zclaw-saas/src/db.rs:14` |
| CP-4 | Relay handler 持有 config 读锁进行 DB 操作 | Medium | `crates/zclaw-saas/src/relay/handlers.rs:161-166` |
### 2.3 异步锁模式
| 位置 | 锁类型 | 跨 await? | 风险 |
|------|--------|----------|------|
| `loop_runner.rs:4` | std::sync::Mutex | 否 | Low |
| `loop_guard.rs:8` | std::sync::Mutex | 否 | Low |
| `memory.rs:25,33` | std::sync::Mutex | 否 | Low |
| `viking_adapter.rs:114-123` | std::sync::RwLock | 可能 (async trait) | Medium |
### 2.4 热路径分析
| ID | 发现 | 风险 |
|----|------|------|
| CL-1 | `messages.clone()` 每次迭代复制完整消息历史 | Medium |
| CL-3 | `request_body.to_string()` 在重试循环中重复克隆 | Medium |
| MS-1 | SSE usage 记录无限 spawned tasks | High |
| MS-2 | WebSocket 无消息大小限制 | Medium |
---
## 维度 3安全审计
### 3.1 机密管理 (最需改进)
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| **SEC-1** | `saas-config.toml` 含 DB 密码且被 Git 追踪 | **Critical** | `saas-config.toml:16` |
| SEC-2 | 硬编码开发 fallback 密钥存在于 release 构建中 | High | `crates/zclaw-saas/src/config.rs:238,280` |
| SEC-3 | 加密密钥无轮换机制 | Medium | `crates/zclaw-saas/src/config.rs:250-291` |
| SEC-4 | API key 加密复用 TOTP 密钥 | Medium | `crates/zclaw-saas/src/config.rs:250-253` |
### 3.2 认证保护
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| **RATE-1** | 公共认证端点完全绕过速率限制 | **Critical** | `crates/zclaw-saas/src/main.rs:155-182` |
| AUTH-2 | TOTP 无暴力破解保护 | High | `crates/zclaw-saas/src/auth/totp.rs:84-102` |
| AUTH-3 | IP 地址提取信任 X-Forwarded-For | Medium | `crates/zclaw-saas/src/auth/mod.rs:88-104` |
| AUTH-5 | Argon2 使用隐含默认参数 | Medium | `crates/zclaw-saas/src/auth/password.rs:17` |
### 3.3 SSRF 防护
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| SSRF-2 | 十六进制/八进制正则误报 | Medium | `crates/zclaw-saas/src/relay/service.rs:491` |
| SSRF-3 | DNS rebinding 未缓解 | Medium | `crates/zclaw-saas/src/relay/service.rs:503-518` |
### 3.4 数据保护
| ID | 发现 | 风险 | 文件 |
|----|------|------|------|
| **CRYPTO-1** | Provider API 密钥在数据库中明文存储 | **Critical** | `crates/zclaw-saas/src/relay/key_pool.rs:278` |
| XSS-1 | `dangerouslySetInnerHTML` 渲染未净化内容 | Medium | `desktop/src/components/PipelineResultPreview.tsx:189` |
| SQL-1 | 所有查询使用参数化绑定 | Info | 全部 SQL 文件 |
### 安全态势评估
| 领域 | 评级 | 说明 |
|------|------|------|
| SQL 注入防御 | 优秀 | 全量参数化查询 |
| 密码哈希 | 良好 | Argon2id + spawn_blocking |
| JWT 实现 | 良好 | 类型区分 + 刷新轮换 + 数据库验证 |
| 加密实现 | 良好 | AES-256-GCM + 随机 nonce |
| SSRF 深度防御 | 良好 | 多层验证 |
| 机密管理 | 差 | 硬编码 + Git 泄露 + 无轮换 |
| 认证端点保护 | 差 | 公共路由无速率限制 |
| API 密钥存储 | 差 | 明文存储 |
---
## 维度 4UX/功能完整性
### 4.1 Admin V2 健壮性
| ID | 发现 | 风险 |
|----|------|------|
| **UX-01** | 无 Error Boundary渲染异常崩溃整个管理面板 | High |
| UX-02 | Auth token 明文存储在 localStorage | High |
| UX-03 | AuthGuard 仅检查 token 存在性,不验证有效性 | Medium |
| UX-04 | Config 页面内联编辑无确认直接保存 | Medium |
| UX-05 | Provider 删除操作部分页面缺少 Popconfirm | Medium |
| UX-06 | 401 刷新失败时直接 `window.location.href` 重定向 | Medium |
### 4.2 Admin V2 页面评分卡
| 页面 | 加载状态 | 错误状态 | 空状态 | 破坏性确认 | 表单验证 |
|------|---------|---------|--------|-----------|---------|
| Dashboard | ✅ | ✅ | ✅ | N/A | N/A |
| Accounts | ✅ | ✅ | ⚠️ | ✅ Popconfirm | ✅ |
| AgentTemplates | ✅ | ✅ | ⚠️ | ✅ Popconfirm | ✅ |
| ApiKeys | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| Config | ✅ | ⚠️ | ❌ | ❌ 无确认 | ✅ |
| Logs | ✅ | ⚠️ | ⚠️ | N/A | N/A |
| Models | ✅ | ✅ | ⚠️ | ✅ Popconfirm | ✅ |
| Prompts | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| Providers | ✅ | ✅ | ⚠️ | ⚠️ 部分 | ✅ |
| Relay | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| Usage | ✅ | ✅ | ❌ | N/A | N/A |
### 4.3 Desktop 应用
| ID | 发现 | 风险 |
|----|------|------|
| UX-07 | 41 处 console.log含用户名泄露 | Medium |
| UX-08 | WebSocket 无消息大小限制 | Medium |
| UX-09 | Desktop Vite 代理无超时配置 | Medium |
| UX-10 | SchedulerPanel 991 行,过于庞大 | Low |
| UX-11 | Hands 依赖缺失时用户提示不够清晰 | Low |
| UX-12 | GatewayStore 10 处 `any` 类型 | Low |
---
## 风险热力图
```
影响 → Critical High Medium Low
可能性 ↓
高 [SEC-1, RATE-1, [CW-2, CP-1, [CW-3, MS-1, [FEAT-04,
CRYPTO-1] MS-1] CL-1] SIZE-04]
中 [FEAT-01, CW-1] [SEC-2, AUTH-2, [SSRF-2, UX-04, [LK-04,
UX-01] UX-06] CL-2]
低 [MW-03] [LAYER-01, [AUTH-5, SEC-4, [LAYER-05,
SIZE-01] UX-07] MW-05]
```
---
## 统一问题清单
### P0 — 立即修复(阻塞级,共 6 项)
| # | 问题 | 维度 | 文件 | 修复建议 | 工作量 |
|---|------|------|------|----------|--------|
| F1 | multi-agent 编译错误 | 架构 | `kernel.rs:444` | `config` clone before move | 0.5h |
| F2 | saas-config.toml 含密码被 Git 追踪 | 安全 | `saas-config.toml` | `git rm --cached` + 轮换密码 | 0.5h |
| F3 | 硬编码开发密钥在 release 构建中 | 安全 | `config.rs:238,280` | `#[cfg(debug_assertions)]` 门控 | 1h |
| F4 | 公共认证端点无速率限制 | 安全 | `main.rs:155-182` | 添加独立限制 20RPM | 2h |
| F5 | SSE 流被 15s TimeoutLayer 中断 | 性能 | `main.rs:187` | 排除 relay 路由 | 1h |
| F6 | Provider API 密钥明文存储 | 安全 | `key_pool.rs:278` | 调用 encrypt_value | 1h |
### P1 — 本迭代修复(共 12 项)
| # | 问题 | 维度 | 文件 | 修复建议 | 工作量 |
|---|------|------|------|----------|--------|
| F7 | Admin V2 无 Error Boundary | UX | `main.tsx` | 添加全局错误边界 | 2h |
| F8 | 客户端断开上游不取消 | 性能 | `relay/service.rs:252` | CancellationToken 传播 | 3h |
| F9 | SSE usage 记录无限 spawned tasks | 性能 | `relay/service.rs:301` | 信号量限制 + 批量写入 | 2h |
| F10 | Key pool 选择 11 次顺序查询 | 性能 | `relay/key_pool.rs:43` | JOIN + 内存缓存 | 3h |
| F11 | 连接池无熔断器 | 性能 | `db.rs:14` | 80% 阈值返回 503 | 2h |
| F12 | Worker 重试不重新入队 | 架构 | `workers/mod.rs:179` | 重新入队 + 死信队列 | 2h |
| F13 | TOTP 无暴力破解保护 | 安全 | `auth/totp.rs` | 5次失败/分钟限制 | 1h |
| F14 | SSRF blocked_exact 不完整 | 安全 | `relay/service.rs:468` | 移除冗余,依赖 is_private_ip | 1h |
| F15 | SQL 迁移解析器按 `;` 分割 | 架构 | `db.rs:93` | 状态机解析 | 3h |
| F16 | Auth token 明文 localStorage | UX | `authStore.ts:61-68` | 加密存储或 httpOnly cookie | 3h |
| F17 | async 上下文 std::sync 锁 | 性能 | `viking_adapter.rs:114` | 替换为 tokio::sync | 1h |
| F18 | XSS: dangerouslySetInnerHTML | 安全 | `PipelineResultPreview.tsx:189` | sanitizeHtml | 0.5h |
### P2 — 下迭代修复(共 12 项)
| # | 问题 | 维度 | 文件 |
|---|------|------|------|
| F19 | 非 workspace 依赖声明 | 架构 | `zclaw-saas/Cargo.toml` |
| F20 | console.log 清理 (41处) | UX | `desktop/src/` 16 文件 |
| F21 | clone 密度过高 (65+78) | 性能 | `kernel.rs`, `loop_runner.rs` |
| F22 | panic! 用于 CORS 验证 | 架构 | `main.rs:128` |
| F23 | Demo 数据单条 INSERT | 性能 | `db.rs` |
| F24 | kernel.rs God-object 1453行 | 架构 | `kernel.rs` |
| F25 | loop_runner 流式/非流式重复 | 架构 | `loop_runner.rs` |
| F26 | TS client 4文件超1200行 | 架构 | `desktop/src/lib/` |
| F27 | DNS rebinding 未缓解 | 安全 | `relay/service.rs` |
| F28 | IP 头欺骗影响审计日志 | 安全 | `auth/mod.rs:88` |
| F29 | Desktop 代理无超时 | 性能 | `desktop/vite.config.ts` |
| F30 | Argon2 隐含默认参数 | 安全 | `auth/password.rs:17` |
### P3 — 待办(共 10 项)
| # | 问题 | 维度 | 文件 |
|---|------|------|------|
| F31 | serde_yaml 弃用 | 架构 | `zclaw-pipeline/Cargo.toml` |
| F32 | API key/TOTP 密钥分离 | 安全 | `config.rs:251` |
| F33 | 密钥轮换机制 | 安全 | `config.rs:250-291` |
| F34 | Token 类型强制执行 | 安全 | `auth/jwt.rs:92` |
| F35 | 速率限制粒度不足 | 安全 | `middleware.rs` |
| F36 | 错误消息泄露加密细节 | 安全 | `crypto.rs:23,30` |
| F37 | Desktop 直连 L1/L2 crate | 架构 | `desktop/src-tauri/Cargo.toml` |
| F38 | Pipeline 向上依赖 Kernel | 架构 | `zclaw-pipeline/Cargo.toml` |
| F39 | Config 页面无确认保存 | UX | `Config.tsx` |
| F40 | 加密错误消息泛化 | 安全 | `crypto.rs` |
---
## 整改方案时间线
### 第 1 周P0 修复6 项,~6h
1. 修复 `kernel.rs:444` 编译错误
2. `git rm --cached saas-config.toml` + 轮换密码
3. 开发密钥 `#[cfg(debug_assertions)]` 门控
4. 公共认证端点添加速率限制
5. 排除 relay 路由的 TimeoutLayer
6. `add_provider_key` 调用 `encrypt_value`
### 第 2 周P1 修复12 项,~23h
- Admin V2 Error Boundary + Auth token 加密
- CLOSE_WAIT 根因修复CancellationToken + spawned tasks 限制)
- 连接池优化JOIN 查询 + 熔断器)
- TOTP 暴力破解防护
- Worker 重试入队
- SQL 迁移解析器升级
### 第 3-4 周P2 修复12 项,~20h
- 依赖声明统一 + console.log 清理
- kernel.rs 拆分重构
- DNS rebinding 缓解
- 性能优化clone 减少、INSERT 批量化)
### 第 5+ 周P3 待办10 项,持续改进)
---
## 附录:验证方式
1. **编译验证**: `cargo check --workspace --features multi-agent`
2. **Git 追踪**: `git ls-files -- saas-config.toml` 应无输出
3. **密钥搜索**: `grep -rn "dev-only|zclaw-dev" crates/` 应仅在 `#[cfg(debug_assertions)]` 块内
4. **速率限制测试**: 对 `/api/v1/auth/login` 发送 >20 RPM 验证返回 429
5. **SSE 流测试**: relay 请求持续 >15s 验证不被 TimeoutLayer 中断
6. **TypeScript**: `npx tsc --noEmit` 无错误
7. **前端构建**: `pnpm build` 成功
8. **Admin V2**: 触发渲染错误验证 Error Boundary 捕获
---
*审计完成于 2026-03-30。全部发现源自只读静态分析未修改任何文件。*