chore: include complete dc refactor implementation and audits
Release / Build & Release (push) Canceled after 0s

This commit is contained in:
kory
2026-10-02 13:23:30 +08:00
parent 192969d7f6
commit 38382d2486
22 changed files with 3022 additions and 8 deletions
+106
View File
@@ -0,0 +1,106 @@
# 审核专家 B:代码实现审计报告
- **审核人**:审核专家 B(外部 Agent)
- **日期**:2026-10-02
- **对象**:`/root/.openclaw/workspace/vps-commander` 全量 Go 实现
- **对照文档**:《VPS-Commander 平滑升级改造与三级安全拦截实施方案》第 7 章
- **方法**:逐行审读安全、协议、执行器、API 四大核心包,非风格审查
- **结论**:**有条件不通过 —— 5 个阻断项未修复前不得进入 Phase 1**
---
## 一、阻断项(Blockers)
### B1. MCP 接口完全绕过三级安全门禁【严重】
- **位置**:`internal/api/mcp_adapter.go`、`internal/mcp/mcp.go`
- **事实**:两文件**零处**引用安全策略。`MCPBackend.ExecCommand/ReadFile/WriteFile/EditBlock/ListAgentMCP/CallAgentMCP`
直接执行,不调用 `requireSecurity`。
- **影响**:`/mcp/sse` 是 AI Agent 实际使用的主接口——安全模型只管住了 REST,
管 Agent 的通道完全敞开。审计过程中以普通 MCP 客户端身份调用 `exec_command` 未触发任何策略检查。
- **判定**:阻断。修复前不得向任何不可信调用方暴露 token。
### B2. 单一全局 token,可自行提权【严重】
- **位置**:`internal/api/api.go` → `UpdateSecuritySettingsJSON`(`/api/v1/security/settings/update`)
- **事实**:仅凭全局 API token 即可修改全局及任意设备的风险等级。实现中无 admin/user 角色区分,
Spec 7.2 假设的 "Admin Web" 不存在。
- **影响**:拿到 token 即拿到 admin,可把任意设备设为 High,三级门禁形同虚设。
- **判定**:阻断。策略变更必须独立鉴权(独立 admin 凭证或 mTLS 管理身份)。
### B3. 设备身份自报,per-device 策略不可执行【严重】
- **位置**:`internal/api/api.go:467`(`device := r.URL.Query().Get("device")`)、
`internal/cluster/manager.go:108`(`device_name` 取自 query)
- **事实**:设备名来自请求参数自报;Agent WS 仅以共享 cluster secret 认证,device_name 自报。
- **影响**:任意 token 持有者可冒充任意设备,挑选策略最松的设备执行。
- **判定**:阻断。需 per-device 凭证(mTLS 或 per-agent token)后 per-device 策略才有意义。
### B4. Session 所有权形同虚设【严重】
- **位置**:`internal/api/api.go:687` `sessionOwner(r)`
- **事实**:owner = 全局 token 的 SHA256。单 token 体系下所有调用者 owner 哈希相同,
`Session.Authorized()` 对任何已认证调用者恒为真。
- **影响**:Spec 7.5.2 的所有权模型空转,任意调用者可读写/注入/终止他人 Session。
- **判定**:阻断。与 B2 同源,需先解决调用者身份体系。
### B5. 未知设备 fail-open【严重】
- **位置**:`internal/security/policy.go` → `EffectiveRisk()`
- **事实**:设备不在策略表中 → 回退 `GlobalRisk`。若 GlobalRisk 为 High,拼错设备名反而获得最高权限。
- **违反**:Spec 7.2.3 明确要求 fail-closed(不得默认放行 High)。
- **判定**:阻断。未知设备应默认拒绝 Medium/High,或拒绝一切非常读操作。
---
## 二、高优先级(Phase 3 前修复)
### H1. Session 清理逻辑错误
- **位置**:`internal/executor/session_manager.go` → `Cleanup()`
- **事实**:以 `StartedAt` 计算所谓“空闲超时”(实为最大生命期);已过期但仍在运行的 session 永不清理(只删已结束的)→ 资源泄漏。
- **违反**:Spec 7.5.4 要求的空闲超时 + 最大生命期双轨制。
### H2. 无 agent 全局 Session 上限与进程创建速率限制
- **位置**:`internal/executor/session_manager.go`
- **事实**:`MaxSessionsPerManager = 16` 仅为单 manager 上限;`Start()` 存在 TOCTOU(解锁→启动进程→加锁复查),并发可短暂超限。
- **违反**:Spec 7.6。
### H3. 审计日志缺失关键字段
- **位置**:`internal/storage/storage.go:279` `Audit()`
- **事实**:无 `actor`、无 `policy_version`、无 `session_id`;命令明文入库,参数中的 secret 直接进 DB。
- **违反**:Spec 7.7。另需敏感参数脱敏。
### H4. Token 允许经 URL query 传递
- **位置**:`internal/auth/auth.go` → `Middleware.Handler`
- **事实**:接受 `?token=` / `?key=` / `?api_key=`。Token 将进入 access log、代理日志。
- **建议**:仅允许 Authorization header。
### H5. Policy version 无单调性校验
- **位置**:`internal/security/policy.go` → `Publish()`
- **事实**:接受任意版本(含回退)。
- **违反**:Spec 7.2.2。
---
## 三、值得肯定的实现
- **Capability 握手已实现**:`Message` 含 `ProtocolVersion`/`AgentVersion`/`Capabilities`,
`manager.go:333` 按能力门控——上一轮 spec 评审的阻断项在代码中已解决。
- **Session ID 使用 `crypto/rand`**(`api.go:698`),不可预测。
- **`edit_block` 使用临时文件 + 原子 rename**(`edit.go:41-62`),含目录 fsync。
- **REST 路径 `requireSecurity` 覆盖完整**:exec/read/write/mcp/edit_block 均接入。
---
## 四、总体评价
实现层面的信任模型实质是“持有 token 即上帝”:单 token 无角色分离(B2)、
设备身份自报(B3)、MCP 主通道零门禁(B1)、Session 所有权空转(B4)。
B1–B4 任一单独成立即足以让三级门禁失效,四者并存。
**在 B1(MCP 加门禁)、B2(策略变更独立鉴权)、B3(设备身份认证)修复并复审前,
不得向不可信调用方暴露 token,不得开放 `start_process` 等新能力给 Agent。**
---
*审核专家 B,2026-10-02*