OpenClaw Exec 审批与生命周期治理:最小权限、等待状态与微信回传
#OpenClaw #Exec审批 #最小权限 #微信
记录 OC-05 的生产审批基线、D2b 审批等待缺陷和 OC-22 微信文本式审批边界。基础插件配置见 《OpenClaw 配置续集》,无审批日常能力见《OpenClaw 本地记忆落地与无审批能力边界》,任务状态见《OpenClaw 后续功能规划》。
一、为什么不能用“始终允许”解决
OpenClaw 的 exec 能触达 shell、网络、Docker 和宿主机文件。把下载或邮件中的一个审批问题转化为通用 shell 放行,会让自然语言、网页内容和 prompt injection 获得远超任务所需的能力。
当前原则是:
1 | 信息获取与固定只读快照 → 无审批 |
审批模型或语义分类器只能补充风险提示,不能替代确定性的权限策略。
二、生产审批基线
实际生效文件位于 OpenClaw 的容器数据挂载中,而不是顶层历史配置。生产基线已统一为:
-
defaults、main、download、heartbeat:
allowlist / on-miss / deny; -
agent 初始 allowlist 为空,再按专用入口逐项增加;
-
askFallback=deny; -
历史命令字段经过脱敏和受限归档;
-
认证字段、命令中的凭据和用户私密正文不进入报告。
部署使用 OpenClaw 官方审批 CLI,变更前建立受限备份并记录哈希。模型路由、Guardian、
cron 和 provider 配置不随审批基线变更。
三、真实询问与拒绝验证
最初的无副作用命令没有弹出审批,不是策略绕过,而是被运行时归类为内置 safe builtin。因此验收改用离线确认、无参数、无写入、无网络、且不属于 builtin/safeBins/allowlist
的外部 no-op:
-
V1 正常创建审批请求,批准前未执行;
-
同类 V2 明确拒绝,且确认未执行;
-
临时 trace 只记录策略判定字段,不记录命令、参数、用户输入、环境变量或凭据;
-
诊断结束后恢复原 bundle 并清理临时副本。
由此证明生产审批基线对未知外部执行真实生效。
四、为什么使用专用入口
日常能力不需要通用 exec:
-
健康检查使用无参数、固定 JSON 的 snapshot;
-
下载查询、暂停、恢复使用有限参数 wrapper;
-
qB 新增、赛马和删除由确定性 Gate、票据和 executor 控制;
-
邮件摘要使用只读 agent;
-
邮件发送与删除继续要求确认。
这种设计把权限绑定到“操作语义 + 参数 schema”,而不是绑定到可被任意拼接的 shell
字符串。
五、D2b 审批等待缺陷
隔离源码分析确认,审批等待和 blocked-tool 自动中止使用两套生命周期。一个合法的长时间审批可能先被恢复逻辑判定为卡死并中止,随后用户看到过期或无效 approval ID。
窄修复需要给特定 session/run/tool-call 注册“合法等待”状态,并包含:
-
明确的过期时间;
-
approval ID 与原 tool call 绑定;
-
批准、拒绝、过期、重启和工具结束时清除;
-
跨 session、跨 sender 和重放全部拒绝。
不能用以下方式规避:
-
增大 OpenClaw 全局超时;
-
放宽通用 shell;
-
让所有 exec 永不回收;
-
由 agent 自己批准自己的命令。
生产修改前只允许精确版本的隔离源码分析、生命周期测试和审阅包。
六、OC-22 微信文本式审批
OpenClaw 2026.6.10 在微信中会把权限请求详情附件化,用户无法像 WebUI 一样直接点击。现有 /approve <id> allow-once|deny 协议可以复用,但必须通过微信渠道做窄适配。
第一阶段只准备文本式最小版本:
1 | 需要审批:执行一次受限操作 |
适配器必须绑定:
-
微信 account;
-
sender;
-
conversation 与 session;
-
approval ID;
-
原始 tool call;
-
过期时间。
非授权联系人、跨会话回复、过期 ID 和重放都必须拒绝。按钮卡片可以以后增加,但不能改变底层批准协议或扩大 allowlist。
七、与下载体系的关系
《OpenClaw 微信安全下载体系》通过确定性 Gate 避免了常见 qB 操作反复进入通用 exec 审批。普通赛马失败项清理可按冻结规则自动完成;用户明确删除已选任务及文件时,仍需要绑定会话的确认。
OC-22 解决的是其他确实需要审批的工具如何在微信中完成交互,不能反向成为下载 agent
访问任意 shell、凭据或 LAN 服务的通道。
八、验收矩阵
正式适配至少覆盖:
| 场景 | 结果 |
|---|---|
| 同一 sender、session、未过期 ID 批准一次 | 仅执行原 tool call 一次 |
| 明确拒绝 | 不执行并结束等待 |
| 非授权联系人 | 拒绝 |
| 跨会话或跨账号 | 拒绝 |
| 过期或重放 | 拒绝 |
| 服务重启 | 等待状态安全清理或恢复,不重复动作 |
| 用户不回复 | 到期失败闭锁 |
2026-08-13 已补齐精确版本证据:OpenClaw 2026.6.10 的完整 upstream commit、当前
Compose 镜像 ID,以及 Weixin 2.4.6 的 registry integrity、tarball SHA-256 和安装包元数据 SHA 均已冻结。真实 Gateway 接缝确认为exec.approval.requested → exec.approval.resolve → exec.approval.resolved,解析端需要
operator.approvals scope。
实现进一步加入 SQLite WAL 持久 CAS:所有状态变化以 revision 条件更新放在
BEGIN IMMEDIATE 事务内,终态同时写 replay tombstone;跨进程竞争只有一个 worker 能取得 pending → submitting。Gateway 的待执行命令不由 adapter 持久化,进程重启后绝不重建或重放旧命令;响应丢失、双重超时、存储故障、身份缺失或 CAS 失败均闭锁为
unknown 或直接拒绝。39 项测试和额外 20 轮重复均通过,日志仍只允许事件、终态和截断
approval ID hash。
生产已通过 Weixin 官方 approvalCapability 接入,只向已配对 sender 开放 Exec 的
allow-once 与 deny,不显示原命令/参数,不提供 allow-always,也不接受 plugin approval。中文层只识别完整的 批准一次 <ID> 和 拒绝 <ID>;account、sender、conversation、session
均以 SHA-256 绑定并持久化,不保存原身份。
最终无副作用验收创建了一个没有执行计划、禁止投递的合成请求,再以本人现有微信 session 的
chat.send(deliver=false) 精确拒绝。Gateway 接受请求、CAS 终态为 rejected、待审批归零;没有发送真实微信,也没有运行命令。OpenClaw 与 qBittorrent 均保持 running/restart0,原
exec-approvals.json 未变化。生产只发生一次 Gateway 内部受控 reload,容器未重启。
九、OC-07:模型只能做只读安全建议
OC-07 被设计为 OC-05 确定性审批层前的只读建议器,而不是授权器。可信网关先完成身份绑定、工具与参数规范化、敏感字段剥离和确定性风险分类;只有仍具备评审资格的最小摘要才会进入模型。输入不含对话、文件或消息正文、原始命令、凭据、真实路径和任意自由文本,输出也只能是固定 JSON:allow-review、needs-human 或 deny-recommendation。
这里的 allow-review 只表示“没有新增升级信号”,仍须回到 OC-05、人工审批和工具自身门禁。组合语义是吸收式的:既有 deny 永远保持拒绝,既有 human-required 永远保持人工,模型不能把它们降级。模型超时、离线、低置信、无效 JSON、额外字段、未知工具、未知或高风险副作用、提示注入信号和版本/关联字段不匹配,全部失败闭锁到人工。
为防止旧结论被重放,审查结果绑定身份摘要、action fingerprint、policy/profile hash、单次 nonce 和 TTL。nonce 在生产中必须由跨 worker 的持久 CAS 单次消费;内存集合只能用于离线 PoC。审计日志只保留允许字段、截断关联 hash、理由码和延迟桶,不记录输入摘要、身份值、参数值、prompt 或模型原始输出。
离线 deterministic mock/validator 已完成 32/32 主测试、100 次完整重复和 1000 例 schema
外字段 fuzz,fail-open=0;deny/human 吸收、注入、重放、CAS、TTL、超时和日志脱敏门禁均通过。随后冻结 Qwen3-4B Q4 的 128 个合成 case、prompt/profile/schema/policy 与模型、
runtime hash:64 个 deterministic case 全绿,但首个模型 case 的冷/热请求分别在
3021/3014 ms 触发固定 3 秒硬超时,没有有效 JSON,均安全回退人工。
因此该 Qwen3-4B profile 的结论是“不晋级”。硬门禁已经给出确定结果,继续原计划的
192 次矩阵只会重复失败并占用 GPU,所以没有继续,也没有事后放宽超时或修改 prompt 来改写结果;OpenClaw、exec approvals、controller、Guardian、真实审批和生产路由均未接线。若后续继续,只能另立并重新授权新 profile,例如确定性压缩 schema/prompt、替代模型、生产级持久 CAS,或仍不接线的 shadow adapter;旧冻结结果必须独立保留。
模型路由和 Guardian 的独立职责见《OpenClaw 模型路由与 Guardian 交接》。
