Appearance
Exec 审批
Exec 审批是配套应用/节点宿主的安全门,允许沙箱代理在真实宿主机(gateway 或 node)上运行命令。可以把它看作一个安全联锁:只有当策略 + allowlist + (可选的)用户审批三者都同意时,命令才会被允许执行。Exec 审批在工具策略和 elevated 门控之上额外生效(除非 elevated 设置为 full 来跳过审批)。有效策略取较严格的一方:tools.exec.* 与审批默认值,若审批字段未设置,则使用 tools.exec 的值。
如果配套应用 UI 不可用,任何需要提示的请求都由 ask 回退处理(默认:deny)。
适用范围
Exec 审批在执行宿主本地执行:
- Gateway 宿主 → Gateway 机器上的
openclaw进程 - 节点宿主 → 节点运行器(macOS 配套应用或无头节点宿主)
信任模型说明:
- Gateway 身份验证的调用者是该 Gateway 的受信任操作员
- 配对节点将受信任的操作员能力延伸到节点宿主
- Exec 审批降低意外执行风险,但不是每用户的身份验证边界
- 批准的节点宿主运行绑定规范执行上下文:规范 cwd、精确 argv、存在时的 env 绑定,以及可用时的固定可执行路径
- 对于 Shell 脚本和直接解释器/运行时文件调用,OpenClaw 还会尝试绑定一个具体的本地文件操作数。如果该文件在审批后但执行前发生变化,运行将被拒绝
macOS 分工:
- 节点宿主服务通过本地 IPC 将
system.run转发给 macOS 应用 - macOS 应用执行审批 + 在 UI 上下文中运行命令
设置与存储
审批存储在执行宿主的本地 JSON 文件中:
~/.openclaw/exec-approvals.json
示例结构:
json
{
"version": 1,
"socket": {
"path": "~/.openclaw/exec-approvals.sock",
"token": "base64url-token"
},
"defaults": {
"security": "deny",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": false
},
"agents": {
"main": {
"security": "allowlist",
"ask": "on-miss",
"askFallback": "deny",
"autoAllowSkills": true,
"allowlist": [
{
"id": "B0C8C0B3-2C2D-4F8A-9A3C-5A4B3C2D1E0F",
"pattern": "~/Projects/**/bin/rg",
"lastUsedAt": 1737150000000,
"lastUsedCommand": "rg -n TODO",
"lastResolvedPath": "/Users/user/Projects/.../bin/rg"
}
]
}
}
}策略旋钮
安全模式(exec.security)
- deny:阻止所有宿主 exec 请求
- allowlist:只允许已 allowlist 的命令
- full:允许一切(等同于 elevated)
询问模式(exec.ask)
- off:从不提示
- on-miss:只在 allowlist 不匹配时提示
- always:每次命令都提示
询问回退(askFallback)
如果需要提示但无法联系到 UI,由回退决定:
- deny:阻止
- allowlist:只在 allowlist 匹配时允许
- full:允许
内联解释器 eval 加固(tools.exec.strictInlineEval)
当 tools.exec.strictInlineEval=true 时,OpenClaw 将内联代码 eval 形式视为仅审批允许,即使解释器二进制本身已在 allowlist 中。
示例:
python -cnode -e、node --eval、node -pruby -eperl -e、perl -Ephp -rlua -eosascript -e
在严格模式下:这些命令仍需明确审批;allow-always 不会自动为其持久化新 allowlist 条目。
Allowlist(每代理)
Allowlist 是每代理的。若存在多个代理,在 macOS 应用中切换要编辑的代理。模式为不区分大小写的 glob 匹配,应解析为二进制路径(仅 basename 的条目会被忽略)。
示例:
~/Projects/**/bin/peekaboo~/.local/bin/*/opt/homebrew/bin/rg
每个 allowlist 条目记录:
- id:用于 UI 标识的稳定 UUID(可选)
- 最后使用时间戳
- 最后使用的命令
- 最后解析的路径
自动允许技能 CLI
启用自动允许技能 CLI 后,已知技能引用的可执行文件在节点(macOS 节点或无头节点宿主)上被视为已 allowlist。这通过 Gateway RPC 使用 skills.bins 获取技能 bin 列表。若需要严格的手动 allowlist,请禁用此选项。
重要信任说明:
- 这是一个隐式便利 allowlist,与手动路径 allowlist 条目分开
- 适用于 Gateway 和节点在同一信任边界的受信任操作员环境
- 如需严格的显式信任,保持
autoAllowSkills: false并仅使用手动路径 allowlist 条目
Safe Bins(仅 stdin)
tools.exec.safeBins 定义一小组仅 stdin 的二进制文件(如 cut),它们可以在 allowlist 模式下运行,无需显式 allowlist 条目。Safe bins 拒绝位置文件参数和类路径标记,因此只能对传入流进行操作。将其视为流过滤器的窄快速路径,而非通用信任列表。不要在 safeBins 中添加解释器或运行时二进制文件(如 python3、node、ruby、bash)。
默认安全 bin:
cut、uniq、head、tail、tr、wc
grep 和 sort 不在默认列表中。如果选择加入,请为其非 stdin 工作流保留显式 allowlist 条目。
被拒绝的 safe bin 标志(按二进制文件):
grep:--dereference-recursive、--directories、--exclude-from、--file、--recursive、-R、-d、-f、-rjq:--argfile、--from-file、--library-path、--rawfile、--slurpfile、-L、-fsort:--compress-program、--files0-from、--output、--random-source、--temporary-directory、-T、-owc:--files0-from
默认受信任 safe bin 目录仅为 /bin、/usr/bin。如果 safe bin 可执行文件位于包管理器/用户路径(如 /opt/homebrew/bin),请将其显式添加到 tools.exec.safeBinTrustedDirs。
Safe Bins 与 Allowlist 对比
| 主题 | tools.exec.safeBins | Allowlist(exec-approvals.json) |
|---|---|---|
| 目标 | 自动允许窄 stdin 过滤器 | 显式信任特定可执行文件 |
| 匹配类型 | 可执行文件名 + safe-bin argv 策略 | 已解析的可执行路径 glob 模式 |
| 参数范围 | 受 safe-bin 配置和字面量标记规则限制 | 仅路径匹配;参数由您负责 |
| 典型示例 | head、tail、tr、wc | jq、python3、node、ffmpeg、自定义 CLI |
| 最佳用途 | 管道中的低风险文本转换 | 任何有更广泛行为或副作用的工具 |
自定义配置示例:
json5
{
tools: {
exec: {
safeBins: ["jq", "myfilter"],
safeBinProfiles: {
myfilter: {
minPositional: 0,
maxPositional: 0,
allowedValueFlags: ["-n", "--limit"],
deniedFlags: ["-f", "--file", "-c", "--command"],
},
},
},
},
}小龙虾安全提示:养龙虾时最容易踩的坑是把
safeBins当通用白名单用——把python3或node丢进去,结果代理可以跑任意代码。正确做法是用 allowlist 明确信任,配合strictInlineEval=true加固。
控制 UI 编辑
使用控制 UI → Nodes → Exec approvals 卡片编辑默认值、每代理覆盖和 allowlist。选择范围(Defaults 或某个代理),调整策略,添加/删除 allowlist 模式,然后保存。UI 显示每个模式的最后使用元数据,方便保持列表整洁。
CLI:openclaw approvals 支持 gateway 或节点编辑(参见审批 CLI)。
审批流程
需要提示时,Gateway 向操作员客户端广播 exec.approval.requested。控制 UI 和 macOS 应用通过 exec.approval.resolve 解决,然后 Gateway 将批准的请求转发到节点宿主。
对于 host=node,审批请求包含规范的 systemRunPlan 载荷。Gateway 在转发批准的 system.run 请求时,以该计划作为权威命令/cwd/会话上下文。
解释器/运行时命令
批准支持的解释器/运行时运行是保守的:
- 始终绑定精确的 argv/cwd/env 上下文
- 直接 Shell 脚本和直接运行时文件形式会尽力绑定到一个具体的本地文件快照
- 常见包管理器包装形式(如
pnpm exec、npm exec)在绑定前会被解包
审批等待时,exec 工具立即返回审批 id。使用该 id 关联后续系统事件(Exec finished / Exec denied)。
确认对话框包含:
- 命令 + 参数
- cwd
- 代理 id
- 解析的可执行路径
- 宿主 + 策略元数据
操作:
- Allow once → 立即运行
- Always allow → 添加到 allowlist + 运行
- Deny → 阻止
审批转发到聊天频道
可以将 exec 审批提示转发到任意聊天频道,并通过 /approve 批准。这使用标准出站传递管道。
配置:
json5
{
approvals: {
exec: {
enabled: true,
mode: "session", // "session" | "targets" | "both"
agentFilter: ["main"],
sessionFilter: ["discord"], // 子字符串或正则
targets: [
{ channel: "slack", to: "U12345678" },
{ channel: "telegram", to: "123456789" },
],
},
},
}在聊天中回复:
/approve <id> allow-once
/approve <id> allow-always
/approve <id> deny/approve 命令同时处理 exec 审批和插件审批。如果 ID 不匹配待处理的 exec 审批,它会自动检查插件审批。
插件审批转发
插件审批转发使用与 exec 审批相同的传递管道,但有自己独立的 approvals.plugin 配置。
json5
{
approvals: {
plugin: {
enabled: true,
mode: "targets",
agentFilter: ["main"],
targets: [
{ channel: "slack", to: "U12345678" },
{ channel: "telegram", to: "123456789" },
],
},
},
}支持交互式 exec 审批按钮的频道(如 Telegram)也会为插件审批渲染按钮。
内置聊天审批客户端
Discord 和 Telegram 也可以作为显式 exec 审批客户端:
- Discord:
channels.discord.execApprovals.* - Telegram:
channels.telegram.execApprovals.*
这些客户端是可选加入的。如果频道未启用 exec 审批,OpenClaw 不会将该频道视为审批界面。
共同行为:
- 只有配置的审批者才能批准或拒绝
- 请求者不需要是审批者
- 启用频道传递时,审批提示包含命令文本
- 如果没有操作员 UI 或配置的审批客户端可接受请求,提示回退到
askFallback
macOS IPC 流程
Gateway -> Node Service (WS)
| IPC (UDS + token + HMAC + TTL)
v
Mac App (UI + approvals + system.run)安全说明:
- Unix socket 模式
0600,token 存储在exec-approvals.json - 同 UID 对等检查
- 挑战/响应(nonce + HMAC token + 请求哈希)+ 短 TTL
系统事件
Exec 生命周期以系统消息形式展示:
Exec running(只有命令超过运行通知阈值时)Exec finishedExec denied
这些消息在节点报告事件后发布到代理会话。
影响说明
- full 权限很强;尽可能优先使用 allowlist
- ask 让您参与循环,同时仍允许快速审批
- 每代理 allowlist 防止一个代理的审批泄漏到其他代理
- 审批只适用于授权发送者发起的宿主 exec 请求
/exec security=full是授权操作员的会话级便利,设计上跳过审批