内置工具

Exec 审批 — 高级配置

高级 Exec 审批主题:safeBins 快速路径、解释器/运行时 绑定,以及将审批转发到聊天渠道(包括原生交付)。 有关核心策略和审批流程,请参阅 Exec 审批

安全二进制文件(仅限 stdin)

tools.exec.safeBins 指定仅限 stdin 的二进制文件(例如 cut),这些文件 无需显式白名单条目即可在白名单模式下运行。安全二进制文件会拒绝 位置文件参数和类似路径的令牌,因此它们只能处理 传入的数据流。应将其视为流过滤器的有限快速路径,而非 通用信任列表。

默认安全二进制文件:

cutuniqheadtailtrwc

grepsort 不在默认列表中。如果选择启用,请为其非 stdin 工作流保留显式 白名单条目。对于安全二进制模式下的 grep, 请通过 -e/--regexp 提供模式;位置模式形式会被拒绝, 因此无法将文件操作数伪装成含义不明确的位置参数。

Argv 验证和禁止的标志

验证仅根据 argv 结构确定(不检查主机文件系统中是否存在 文件),这可避免允许/拒绝差异造成文件存在性预言机 行为。默认安全二进制文件禁止面向文件的选项;长 选项采用失败关闭验证(拒绝未知标志和含义不明确的缩写)。 默认二进制文件中已识别的只读布尔标志(例如 wc -ltr -duniq -c)会被接受,而无法识别的短标志仍然 采用失败关闭策略,并回退到手动审批。

按安全二进制配置文件列出的禁止标志:

  • grep: --dereference-recursive, --directories, --exclude-from, --file, --recursive, -R, -d, -f, -r
  • jq: --argfile, --from-file, --library-path, --rawfile, --slurpfile, -L, -f
  • sort: --compress-program, --files0-from, --output, --random-source, --temporary-directory, -T, -o
  • tail: --follow, --retry, -F, -f
  • wc: --files0-from

安全二进制文件还会强制在执行时将 argv 令牌视为字面文本 (不进行 glob 展开,也不展开 $VARS),这适用于仅限 stdin 的段,因此 无法使用 *$HOME/... 等模式夹带文件读取。awksedjq 始终不能作为安全二进制文件,因为无法验证其语义 仅限 stdin:jq 可以读取环境数据,并从 模块或启动文件加载 jq 代码。对于这些工具,请使用显式白名单条目或审批提示, 而不要使用 safeBins

可信二进制目录

安全二进制文件必须解析自可信二进制目录(系统默认目录以及 可选的 tools.exec.safeBinTrustedDirs)。PATH 条目绝不会被自动信任。 默认可信目录有意保持最小范围:/bin/usr/bin。如果 你的安全二进制可执行文件位于软件包管理器/用户路径中(例如 /opt/homebrew/bin/usr/local/bin/opt/local/bin/snap/bin),请将它们 显式添加到 tools.exec.safeBinTrustedDirs

Shell 链式调用、包装器和多路复用器

当每个顶层段都满足白名单要求(包括安全二进制文件或 Skills 自动允许)时, 允许 Shell 链式调用(&&||;)。 白名单模式仍不支持重定向。白名单解析期间会拒绝命令替换 ($() / 反引号),包括双引号内的命令替换;如果需要字面 $() 文本,请使用单引号。

对于 macOS 配套应用审批,包含 Shell 控制或 展开语法(&&||;|`$<>())的原始 Shell 文本 会被视为白名单未命中,除非 Shell 二进制文件本身已加入白名单。

对于 Shell 包装器(bash|sh|zsh ... -c/-lc),请求范围内的环境变量覆盖 会缩减为一个较小的显式白名单(TERMLANGLC_*COLORTERMNO_COLORFORCE_COLOR)。

对于白名单模式下的 allow-always 决策,透明调度包装器 (例如 envflocknicenohupstdbuftimeout)会持久化 内部可执行文件路径,而非包装器路径。Shell 多路复用器 (busyboxtoybox)也会以相同方式针对 Shell 小程序(shash 等)解除包装。 如果无法安全地解除包装器或多路复用器,则不会自动持久化任何白名单 条目。

如果将 python3node 等解释器加入白名单,请优先使用 tools.exec.strictInlineEval=true,这样内联求值仍需显式 审批。在严格模式下,allow-always 仍可持久化无害的 解释器/脚本调用,但不会自动持久化内联求值载体。

安全二进制文件与白名单的对比

主题 tools.exec.safeBins 白名单(exec-approvals.json
目标 自动允许有限的 stdin 过滤器 显式信任特定可执行文件
匹配类型 可执行文件名称 + 安全二进制 argv 策略 已解析的可执行文件路径 glob,或用于通过 PATH 调用的命令的裸命令名 glob
参数范围 受安全二进制配置文件和字面令牌规则限制 默认匹配路径;可选的 argPattern 可限制解析后的 argv
典型示例 headtailtrwc jqpython3nodeffmpeg、自定义 CLI
最佳用途 流水线中的低风险文本转换 任何行为范围更广或具有副作用的工具

配置位置:

  • safeBins 来自配置(tools.exec.safeBins 或按 Agent 配置的 agents.entries.*.tools.exec.safeBins)。
  • safeBinTrustedDirs 来自配置(tools.exec.safeBinTrustedDirs 或按 Agent 配置的 agents.entries.*.tools.exec.safeBinTrustedDirs)。
  • safeBinProfiles 来自配置(tools.exec.safeBinProfiles 或按 Agent 配置的 agents.entries.*.tools.exec.safeBinProfiles)。按 Agent 配置的配置文件键会覆盖全局键。
  • 白名单条目位于 agents.<id>.allowlist 下的主机本地审批文件中(也可通过 Control UI / openclaw approvals allowlist ... 管理)。
  • 当解释器/运行时二进制文件出现在 safeBins 中但没有显式配置文件时,openclaw security audit 会通过 tools.exec.safe_bins_interpreter_unprofiled 发出警告。
  • openclaw doctor --fix 可以将缺失的自定义 safeBinProfiles.<bin> 条目搭建为 {}(之后请检查并收紧配置)。不会自动搭建解释器/运行时二进制文件。

自定义配置文件示例:

json5
{  tools: {    exec: {      safeBins: ["myfilter"],      safeBinProfiles: {        myfilter: {          minPositional: 0,          maxPositional: 0,          allowedValueFlags: ["-n", "--limit"],          deniedFlags: ["-f", "--file", "-c", "--command"],        },      },    },  },}

解释器/运行时命令

由审批支持的解释器/运行时执行有意采取保守策略:

  • 始终绑定确切的 argv/cwd/env 上下文。
  • 直接 Shell 脚本和直接运行时文件形式会尽最大努力绑定到一个具体的本地 文件快照。
  • 仍可解析到一个直接本地文件的常见软件包管理器包装形式(例如 pnpm execpnpm nodenpm execnpx)会在绑定前解除包装。
  • 如果 OpenClaw 无法为解释器/运行时命令识别出恰好一个具体的本地文件 (例如软件包脚本、求值形式、运行时特有的加载器链或含义不明确的多文件 形式),则会拒绝由审批支持的执行,而不会声称提供了实际上并不具备的语义 覆盖。
  • 对于这些工作流,请优先使用沙箱隔离、独立的主机边界,或显式可信的 白名单/完整工作流,由操作员接受更广泛的运行时语义。

需要审批时,Exec 工具会立即返回审批 ID。使用该 ID 关联之后已获批准执行的系统事件(Exec finished,以及配置后的 Exec running)。 如果超时前未收到决定,则请求会被视为审批超时,并 作为最终主机命令拒绝呈现。对于具有来源会话的主 Agent 异步审批, OpenClaw 还会通过内部后续消息恢复该会话,使 Agent 知道 命令并未执行,而不是之后再修复缺失的结果。默认情况下,待处理的 Exec 审批会在 30 分钟后过期。

后续交付行为

获批的异步 Exec 完成后,OpenClaw 会向同一会话发送后续 agent 轮次。 被拒绝的异步审批使用相同的主会话后续路径传递拒绝状态,但不会 注册提升权限的运行时交接,也不会运行命令。如果拒绝没有可恢复的 主会话,则会抑制该拒绝,或在存在安全直接路由时通过该路由报告。

  • 如果存在有效的外部交付目标(可交付渠道加目标 to),后续交付将使用该渠道。
  • 在没有外部目标、仅限 Webchat 或内部会话的流程中,后续交付仅保留在会话内(deliver: false)。
  • 如果调用方在没有可解析外部渠道时明确请求严格外部交付,请求将以 INVALID_REQUEST 失败。
  • 如果已启用 bestEffortDeliver 且无法解析外部渠道,交付会降级为仅限会话,而不是失败。

第三方客户端的最小权限范围

Gateway 网关审批解析受专用 operator.approvals 权限范围保护。这同时适用于所有者专用的 exec.approval.resolve 方法和与种类无关的 approval.resolve 方法;operator.write 并不包含该权限。仪表板和集成应仅请求其所用方法所需的权限范围。应将审批解析访问权限视为远程执行级权限,并有意授予 operator.approvals,即使客户端仅呈现一个小型审批 UI。

将审批转发到聊天渠道

你可以将 Exec 审批提示转发到任何聊天渠道(包括插件渠道),并通过 /approve 审批。这使用常规的出站投递流水线。

配置:

json5
{  approvals: {    exec: {      enabled: true,      mode: "session", // "session" | "targets" | "both"      agentFilter: ["main"],      sessionFilter: ["discord"], // substring or regex      targets: [        { channel: "slack", to: "U12345678" },        { channel: "telegram", to: "123456789" },      ],    },  },}

在聊天中回复:

Code
/approve <id> allow-once/approve <id> allow-always/approve <id> deny

/approve 命令同时处理 Exec 审批和插件审批。如果 ID 与待处理的 Exec 审批不匹配,它会自动改为检查插件审批。此回退仅限于“找不到审批”故障;真正的 Exec 审批拒绝或错误不会静默地以插件审批方式重试。

插件审批转发

插件审批转发使用与 Exec 审批相同的投递流水线,但在 approvals.plugin 下具有独立配置。启用或禁用其中一项不会影响另一项。有关插件开发行为、请求字段和决策语义,请参阅插件权限请求

json5
{  approvals: {    plugin: {      enabled: true,      mode: "targets",      agentFilter: ["main"],      targets: [        { channel: "slack", to: "U12345678" },        { channel: "telegram", to: "123456789" },      ],    },  },}

配置结构与 approvals.exec 相同:enabledmodeagentFiltersessionFiltertargets 的工作方式相同。

支持共享交互式回复的渠道会为 Exec 审批和插件审批呈现相同的审批按钮。没有共享交互式 UI 的渠道会回退到包含 /approve 指令的纯文本。插件审批请求可能会限制可用决策:审批界面使用请求中声明的决策集,Gateway 网关会拒绝提交未提供的决策。

任意渠道中的同一聊天审批

当 Exec 或插件审批请求源自可投递的聊天界面时,默认情况下,同一聊天可以使用 /approve 审批该请求。除了现有的 Web UI 和终端 UI 流程之外,这也适用于 Slack、Matrix、Microsoft Teams 及类似的可投递聊天,并使用该对话的常规渠道身份验证模型。如果来源聊天已经能够发送命令并接收回复,审批请求便不再需要单独的原生投递适配器来保持待处理状态。

Discord、Telegram 和 QQ Bot 也支持同一聊天中的 /approve,但即使原生审批投递已禁用,这些渠道仍会使用其解析出的审批人列表进行授权。

原生审批投递

某些渠道还可充当原生审批客户端:Discord、Slack、Telegram、Matrix 和 QQ Bot。原生客户端在共享的同一聊天 /approve 流程之上,增加审批人私信、来源聊天扇出和渠道特定的交互式审批体验。

当原生审批卡片或按钮可用时,该原生 UI 是面向智能体的主要路径。除非工具结果表明聊天审批不可用,或手动审批是唯一剩余路径,否则智能体不应再回显重复的纯聊天 /approve 命令。

如果已配置原生审批客户端,但来源渠道没有活跃的原生运行时,OpenClaw 会保持显示本地确定性的 /approve 提示。如果原生运行时处于活跃状态并尝试投递,但没有目标收到卡片,OpenClaw 会发送同一聊天回退通知,其中包含确切的 /approve <id> <decision> 命令,以便仍能处理该请求。

通用模型:

  • 主机 Exec 策略仍决定是否需要 Exec 审批
  • approvals.exec 控制是否将审批提示转发到其他聊天目的地
  • channels.<channel>.execApprovals 控制是否启用 Discord、Slack、Telegram、QQ Bot 及类似的渠道特定原生客户端
  • 当请求来自 Slack 且能够解析出 Slack 插件审批人时,Slack 插件审批可以使用 Slack 的原生审批客户端;即使 Slack Exec 审批已禁用,approvals.plugin 也可以将插件审批路由到 Slack 会话或目标
  • 当能够从 dm.allowFromdefaultTo 解析出稳定的 users/<id> 审批人时,Google Chat 原生审批卡片会处理源自 Google Chat 空间或话题串的 Exec 和插件审批;它们不使用表情回应事件来作出决策
  • WhatsApp 和 Signal 表情回应审批投递受 approvals.execapprovals.plugin 控制;它们没有 channels.<channel>.execApprovals

当以下所有条件均成立时,原生审批客户端会自动启用以私信优先的投递:

  • 渠道支持原生审批投递
  • 可以从显式的 execApprovals.approverscommands.ownerAllowFrom 等所有者身份解析出审批人
  • channels.<channel>.execApprovals.enabled 未设置或为 "auto"

enabled: false 设置为显式禁用原生审批客户端。将 enabled: true 设置为在能够解析出审批人时强制启用。公开的来源聊天投递仍需通过 channels.<channel>.execApprovals.target 显式启用。当原生 target 启用来源聊天投递时,审批提示会包含命令文本。

常见问题:为什么聊天审批有两项 Exec 审批配置?

  • Discord:channels.discord.execApprovals.*
  • Slack:channels.slack.execApprovals.*
  • Telegram:channels.telegram.execApprovals.*
  • QQ Bot:channels.qqbot.execApprovals.*
  • Google Chat:使用 channels.googlechat.dm.allowFromchannels.googlechat.defaultTo 配置稳定的审批人;不需要 execApprovals
  • WhatsApp:使用 approvals.execapprovals.plugin 将审批提示路由到 WhatsApp
  • Signal:使用 approvals.execapprovals.plugin 将审批提示路由到 Signal

原生客户端特定路由:

  • Telegram 默认向审批人发送私信(target: "dm")。切换为 channelboth,也可以在来源 Telegram 聊天或话题中显示审批提示。对于 Telegram 论坛话题,OpenClaw 会为审批提示和审批后的后续消息保留该话题。
  • Discord 和 Telegram 审批人可以显式指定(execApprovals.approvers),也可以从 commands.ownerAllowFrom 推断;只有解析出的审批人才能批准或拒绝。
  • Slack 审批人可以显式指定(execApprovals.approvers),也可以从 commands.ownerAllowFrom 推断。Slack 插件审批私信使用来自 allowFrom 的 Slack 插件审批人和账户默认路由,而不是 Slack Exec 审批人。Slack 原生按钮会保留审批 ID 类型,因此 plugin: ID 可以处理插件审批,而不需要第二层 Slack 本地回退。
  • Google Chat 原生卡片会在消息文本中保留手动 /approve 回退,但卡片按钮回调仅携带不透明操作令牌;审批 ID 和决策会从服务器端待处理状态中恢复。
  • 当匹配的顶层转发类别路由到 WhatsApp 时,WhatsApp 表情符号审批会处理 Exec 和插件提示。原生来源提示会直接绑定;共享目标模式投递会将相同的类型化审批元数据绑定到已接受的 WhatsApp 消息回执。
  • 仅当匹配的顶层转发类别已启用并路由到 Signal 时,Signal 表情回应审批才会处理 Exec 和插件提示。直接在同一 Signal 聊天中进行的 Exec 审批可以在没有显式审批人的情况下抑制本地 /approve 回退;Signal 表情回应解析仍需要来自 channels.signal.allowFromdefaultTo 的显式 Signal 审批人。
  • Matrix 原生私信/渠道路由和表情回应快捷方式会处理 Exec 和插件审批;插件授权仍来自 channels.matrix.dm.allowFrom。Matrix 原生提示会在第一个提示事件中包含 com.openclaw.approval 自定义事件内容,以便支持 OpenClaw 的 Matrix 客户端读取结构化审批状态,而标准客户端仍保留纯文本 /approve 回退。
  • 原生 Discord 和 Telegram 审批按钮在传输私有的回调数据中携带显式的 Exec 或插件所有者类型,并且仅处理该所有者。缺少类型的旧版 /approve 控件仍作为受限的兼容路径:它们只尝试操作者有权审批的所有者类型,仅在得到找不到审批的结果后继续,并且绝不会根据审批 ID 推断所有权。
  • 请求者不需要是审批人。
  • 如果没有操作员 UI 或已配置的审批客户端能够接受请求,提示会回退到 askFallback

/diagnostics/export-trajectory 等仅限所有者使用的敏感群组命令,会对审批提示和最终结果使用私有所有者路由。OpenClaw 首先尝试在所有者运行命令的同一界面上使用私有路由。如果该界面没有私有所有者路由,则会回退到 commands.ownerAllowFrom 中第一个可用的所有者路由,因此,当 Telegram 是已配置的主要私有界面时,Discord 群组命令仍可将审批和结果发送到所有者的 Telegram 私信。群聊只会收到简短的确认消息。

另请参阅:

官方移动端操作员应用

官方 iOS 和 Android 应用也可以审查由 Gateway 网关所有的待处理 Exec 审批,前提是使用 operator.admin 连接,或者请求明确指定了其已配对的 operator.approvals 设备。它们读取 Control UI 所使用的同一份经过净化的持久记录,提交感知类型的决策,并显示 Gateway 网关规范的首次响应结果。Apple Watch 会通过已配对的 iPhone 镜像这些审批提示,并提供允许一次和拒绝操作。Watch 直连 Gateway 网关模式不会审查审批。

丢失处理确认并不会使已提交的选择成为权威结果:应用会禁用控件并再次读取记录。如果另一个界面先完成处理,应用会显示记录中的决策。待处理提示始终绑定到发出它们的 Gateway 网关,因此切换活跃的 Gateway 网关无法重定向旧的审批 ID。

macOS IPC 流程

Code
Gateway 网关 -> 节点服务 (WS)                 |  IPC (UDS + 令牌 + HMAC + TTL)                 v             Mac 应用(UI + 审批 + system.run)

安全说明:

  • Unix 套接字模式 0600,令牌存储在 exec-approvals.json 中。
  • 同一 UID 对等方检查。
  • 质询/响应(随机数 + HMAC 令牌 + 请求哈希)+ 短 TTL。

常见问题

何时会在审批目标上使用 accountIdthreadId

当渠道配置了多个身份,并且审批提示必须通过某个特定账户发出时,使用 accountId。当目的地支持话题或话题串,并且提示应保留在该话题串内而不是顶层聊天中时,使用 threadId

一个具体的 Telegram 示例是具有论坛话题和两个 Telegram Bot 账户的运维超级群组。to 值指定超级群组,accountId 选择 Bot 账户,threadId 选择论坛话题:

json5
{  approvals: {    exec: {      enabled: true,      mode: "targets",      targets: [        {          channel: "telegram",          to: "-1001234567890",          accountId: "ops-bot",          threadId: "77",        },      ],    },  },  channels: {    telegram: {      accounts: {        default: {          name: "Primary bot",          botToken: "env:TELEGRAM_PRIMARY_BOT_TOKEN",        },        "ops-bot": {          name: "Operations bot",          botToken: "env:TELEGRAM_OPS_BOT_TOKEN",        },      },    },  },}

采用该设置后,转发的 Exec 审批会由 ops-bot Telegram 账号发布到聊天 -1001234567890 的话题 77 中。未指定 accountId 的目标使用该渠道的默认账号,未指定 threadId 的目标则发布到顶层目的地。

将审批发送到会话后,该会话中的任何人都能批准吗?

不能。会话投递仅控制提示出现的位置。它本身并不会授权该聊天中的所有 参与者进行批准。

对于通用的同聊天 /approve,发送者必须已经获得在该 渠道会话中使用命令的授权。如果渠道公开了明确的审批批准者,那么即使这些批准者在该会话中没有其他命令授权,也可以授权 /approve 操作。

某些渠道更为严格。Discord、Telegram、Matrix、Slack 原生审批私信以及类似的 原生审批客户端使用其解析出的批准者列表进行审批授权。例如, Telegram 论坛话题中的审批提示可能对话题内的所有人可见,但只有从 channels.telegram.execApprovals.approverscommands.ownerAllowFrom 解析出的数字 Telegram 用户 ID 才能批准或拒绝该提示。

相关内容

Was this useful?
On this page

On this page