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 |
低风险,纳入待办 |
推荐立即行动项
- SEC-1:
saas-config.toml 含数据库密码且被 Git 追踪 → git rm --cached
- FEAT-01:
kernel.rs:444 multi-agent 编译错误 → 修改变量名
- RATE-1: 公共认证端点无速率限制 → 添加限制
- CW-1: 15s TimeoutLayer 中断 SSE 流 → 排除 relay 路由
- CRYPTO-1: Provider API 密钥明文存储在数据库 → 启用加密
- UX-01: Admin V2 无 Error Boundary → 添加全局错误边界
架构依赖图
图例: 黄色节点表示存在架构违规
维度 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 密钥存储 |
差 |
明文存储 |
维度 4:UX/功能完整性
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 |
风险热力图
统一问题清单
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)
- 修复
kernel.rs:444 编译错误
git rm --cached saas-config.toml + 轮换密码
- 开发密钥
#[cfg(debug_assertions)] 门控
- 公共认证端点添加速率限制
- 排除 relay 路由的 TimeoutLayer
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 项,持续改进)
附录:验证方式
- 编译验证:
cargo check --workspace --features multi-agent
- Git 追踪:
git ls-files -- saas-config.toml 应无输出
- 密钥搜索:
grep -rn "dev-only|zclaw-dev" crates/ 应仅在 #[cfg(debug_assertions)] 块内
- 速率限制测试: 对
/api/v1/auth/login 发送 >20 RPM 验证返回 429
- SSE 流测试: relay 请求持续 >15s 验证不被 TimeoutLayer 中断
- TypeScript:
npx tsc --noEmit 无错误
- 前端构建:
pnpm build 成功
- Admin V2: 触发渲染错误验证 Error Boundary 捕获
审计完成于 2026-03-30。全部发现源自只读静态分析,未修改任何文件。