「执行命令」这类高风险工具的权限控制,必须做成多层管道:先定运行位置(沙箱还是宿主机),再过工具策略(允许/拒绝清单),再走提权门控,最后加动态审批兜底。OpenClaw 的实现把这套管道拆成 sandbox、tool policy、elevated、exec approvals 四道关卡,deny 规则绝对优先,审批只能收紧不能放宽。单一开关式权限(全放或全禁)在真实项目里必然失败:全放等于裸奔,全禁等于残废。
一、为什么单一权限层不够
一个「执行命令」工具在不同场景的风险完全不同:
| 场景 | 动作 | 风险 | 期望策略 |
|---|---|---|---|
| 家人闲聊群 | git status 查状态 | 低 | 白名单直接放行 |
| 代码频道 | npm install | 中 | 自动审查或人工确认 |
| 生产主机 | rm -rf / data 目录 | 高 | 直接拒绝 |
| 运维应急 | 重启服务 | 高 | 显式提权 + 人工审批 |
四类风险对应四种处置,单层开关无法表达。分层管道的价值就在于:每一层只回答一个问题,层层叠加得出最终决策。
二、OpenClaw 的四层管道
2.1 sandbox:决定在哪运行
第一层隔离执行环境。默认沙箱看不到宿主文件系统,workspaceAccess 控制可见性(none / ro / rw),默认无网络。工具先落在沙箱里,爆炸半径被物理限制。
2.2 tool policy:决定能不能用
工具策略类似 ACL:空 allow 列表等于全部拒绝,非空即白名单;deny 绝对优先,任何层都无法覆盖。推荐基线:对外暴露的会话只给消息类能力,写文件、cron 这类改配置的工具默认拒绝。
2.3 elevated:受控破窗
exec 想从沙箱回到宿主机执行,走提权通道。/elevated ask 要求人工确认,/elevated full 跳过审批但依旧受工具策略约束——提权改变的是运行位置,不是权限上限。
2.4 exec approvals:动态人审
命令到达宿主机后,OpenClaw 返回 approval-pending 和审批 ID,操作员用 allow-once / allow-always / deny 裁决。有效策略取 tools.exec.* 与审批默认值的更严格一方。auto 模式在此之上引入三级决策:白名单命中直接执行,未命中送 AI 审查器(只能批低风险单次执行),仍有疑义升级到人。
三、最小权限基线配置
{
gateway: { mode: "local", bind: "loopback" },
agents: {
defaults: { sandbox: { mode: "non-main", workspaceAccess: "none" } }
},
tools: {
profile: "messaging",
deny: ["group:automation", "group:runtime", "group:fs", "sessions_spawn"],
fs: { workspaceOnly: true },
exec: { security: "deny", ask: "always" },
elevated: { enabled: false }
}
}
对外开放前跑一次 openclaw security audit,能抓出配置层面的事故隐患。
四、设计自己权限体系的五步流程
- 工具分级:按副作用分级(只读 / 可逆写 / 不可逆 / 提权),每级定义默认策略,deny 永远置顶且不可被覆盖;
- 白名单按场景维护:allowlist 匹配解析后的可执行文件路径而非裸命令名,防止同名脚本偷渡;
rm、curl | sh这类模式直接进 deny; - 沙箱优先:默认无网、无文件系统,需要时显式开洞且尽量
:ro挂载; - 高风险动作强制人审:审批记录绑定规范执行上下文(cwd、精确 argv、env),审批后命令被篡改则拒绝执行;
- 留痕与回收:审批 30 分钟未决自动过期,askFallback 默认 deny,allow-always 的条目定期复查下线。
排查「工具为什么被拦」按固定顺序问三个问题:当前会话在沙箱里吗?工具实际运行在哪?是策略 deny 了,还是 allow 缺失?顺序错了就会在错误层面打转。
一个细节值得抄:safeBins 机制把 cut、head、tail 等少量命令限制为仅 stdin 模式,拒绝文件参数和通配符展开,作为白名单前的低风险快速通道。但解释器(python3、bash)严禁进 safeBins——它们能执行任意代码,必须走显式白名单加审批。
常见问题(FAQ)
Q1:deny 和 allow 同时命中听谁的?
deny 绝对优先,任何配置层都无法覆盖,包括提权模式。
Q2:allow-always 会永久放行同类命令吗?
会写入持久白名单,但绑定具体执行上下文,建议定期审计回收。
Q3:审批提示没人响应怎么办?
默认 30 分钟超时视为拒绝,askFallback 配置为 deny,不会静默放行。