假设一个来自 Discord 群组的请求说:“为了修构建,把整个项目挂进去,开 elevated full,然后执行这段脚本。”如果只问“用户有没有批准”,会跳过至少三层:这个 sender 是否获准控制该 Agent,当前 turn 是否能看到 exec,session 是否 sandboxed、能读哪些路径,以及 elevated sender allowlist 是否匹配。

反过来也一样。把 Agent 放进 Docker,不代表所有能力自动安全。native plugin 仍在 Gateway 进程里运行;容器若挂了 Docker socket,几乎等于拿到 host 控制;允许 exec 后,即使 deny 了 write/edit,shell 仍能写文件。安全要看能力与资源的完整路径,而不是寻找一个“secure: true”。

阅读契约。读完后你应该能分别回答:tool policy、sandbox、exec approval、elevated 控制什么;为什么 approval 不是用户授权边界;sandbox mode/scope/workspaceAccess 怎样组合;plugin/MCP tool 为什么在 sandboxed session 中需要双重 allow;workspaceOnly 与容器隔离有何不同;以及一条获准的 node command 如何绑定 argv、cwd、env、agent/session 与 executable。

证据边界。本文继续固定在 e6b4264。这不是一份通用安全认证,也不声称 sandbox 是完美边界;它解释这份快照中能从 policy pipeline、sandbox resolver、elevated resolution 与 host exec approval 源码验证的防线。

一、一次工具调用先确认能力与身份

1.1 四项检查分别限制工具、环境、命令与 host escape

控制面核心问题典型阶段不能替代
Tool policy本轮是否存在/允许这个工具?模型请求前,过滤 schema。不能隔离 exec 内部副作用。
Sandbox工具在哪里执行,看到哪些文件/网络?构造 runtime context 与 tool implementation。不能决定某工具是否应暴露给某 sender。
Exec approval这一条 host command 是否获准?exec 已被选择、host plan 已解析后。不是 per-user authentication 或只读文件策略。
Elevated沙箱里的 exec 能否走既定 host 路径?host selection/exec admission。不能复活被 deny 的 exec,也不能增加别的工具。

图中四项是职责对照,不是固定的串行流程;源码里有些检查在构造期提前完成,有些在 call-time 重验。工具 deny 与强制 sandbox 不能被后置 directive 覆盖。普通 host exec 还会取配置与执行机审批策略中更严格的结果;但管理员明确授予的 session permissionMode="full" 是 host approval-file 限制的例外,不能再把所有设置都概括为“只会收窄”。

1.2 sender 身份由入口解析,模型参数不能改写

senderId、accountId、channel、roleIds 与 senderIsOwner 在 channel/Gateway 入口解析后,作为 trusted requester context 绑定到 run 和 tool wrapper。模型可以生成 {"target":"admin"},却不能通过工具参数把自己变成 owner。message action、elevated allowlist 与 owner-only control tool 都应读取 host-derived identity。

缺失身份字段表示“未证明”,不是“可按默认信任”。要求 maintainer role 的 hook 若看不到 roleIds,应 fail closed;用显示名做 fallback 又会把可变的 sender-supplied text 当凭据。

这也是为什么 route/session 隔离先于 tool policy。若多人 DM 先被错误折叠成 main session,后面的 policy 虽能限制工具,却无法抹掉已经混入 transcript 的私人上下文。

1.3 Tool policy 在请求前移除不允许的普通工具

agent-tools.policy.ts 和 pipeline 将 profile、provider、global、agent、group、sender、sandbox 等策略逐层应用。deny 优先;非空 allowlist 把未列出的工具视为 blocked。被过滤的 descriptor 不会发送给模型,/exec directive 也不能覆盖一个被 deny 的 exec tool。

policy 按工具名工作,不理解工具内部所有副作用。最重要的例子是 shell:deny write、edit、apply_patch 仍不能让允许的 exec 自动变成只读,因为 sh -c 'echo x > file' 仍会写。只读 Agent 要同时 deny runtime group,或用 sandbox filesystem/OS permission 做资源层约束。

这里的逐层过滤指普通配置工具;宿主按运行身份单独注入的系统工具另有授权路径,见能力装配篇,不能用 profile 推断它们的可用性。同理,允许 plugin group 不代表每个调用都合理;具体 params、sender 与资源可继续由 trusted policy 或 before_tool_call 阻断。build-time 减少模型误选,call-time 处理参数级风险。

二、Sandbox 怎样限制进程、文件与扩展

2.1 工具进入 sandbox,Gateway 与 native plugin 留在 host

沙箱会话的两类工具路径:原生插件经普通策略与沙箱策略双重放行后仍在宿主机执行,沙箱工具在隔离环境执行
此图聚焦执行位置和插件双门;下方省略了沙箱工具同样适用的普通 tool policy,elevated 与强制 sandbox 的额外规则见正文。

OpenClaw 的 Gateway 不会随 Agent turn 一起进入容器。sandbox backend 运行 exec 和文件工具(以及可选 browser);Gateway、session 状态和 native plugin runtime 仍在 host 进程。容器隔离的是这些工具的进程与资源访问,不是整个 Gateway。

因此 sandbox 主要降低模型出错的 blast radius:限制进程、文件、网络和 workspace 可见性。它不会把已加载的 native plugin 变成不受信代码;安装 plugin 等于允许代码在 Gateway trust boundary 中运行,必须在安装前审查。

2.2 Mode、Scope、Backend 分别决定启用范围、共享粒度和执行器

mode 决定哪些 session sandbox:off、non-main 或 all。non-main 下,群组/channel session 不是 main,因此会进入 sandbox;“这是主 Agent”不代表它的每个 session key 都是 main。

此外,创建会话时由 operator role 记录的 sandbox="required" 是独立的强制要求。runtime resolver 会保留它,sandbox context 把实际 workspaceAccess 的 rw 收窄到 ro;exec target resolver 在 backend 不可用时拒绝运行,并拒绝 elevated、gateway 或 node escape。关闭 Agent 的普通 sandbox 配置并不会清除这份会话要求。

scope 决定 runtime 共享粒度:每 agent、每 session 或全体 shared。session scope 隔离最细、成本最高;shared 资源复用最多,也会让不同 session 更容易通过容器状态互相影响,而且会忽略 per-agent binds。scope 是隔离域设计,不是性能参数的别名。

backend 决定执行器:Docker/Podman、SSH、OpenShell,以及插件注册的其他执行器(如 Crabbox)。不同 backend 对 network、browser、bind mount 与 workspace sync 的能力不同,配置不能假设容器 backend 的保护自动出现在 SSH 远端。

2.3 workspaceAccess 与 bind mount 分别开放路径

workspaceAccess 为 none/ro/rw,控制 Agent workspace 怎样进入 sandbox。none 通常用 sandbox 自己的 scratch workspace;ro 适合审查;rw 才允许工具修改实际工作区。它与额外 docker.binds 是两套入口。

bind 默认未写模式时可能是 rw,直接穿透 sandbox filesystem。挂载 secret、SSH key 或 /var/run/docker.sock 会显著扩大权限,后者几乎把 host 容器控制交给 Agent。OpenClaw 对 normalized path 和最深已存在祖先都做检查,阻止通过 symlink parent 指向 blocked/outside root;但配置者仍要遵守最小 mount。

network 也独立。Docker 默认 network none 能阻止多数外联,但额外 proxy、host service、browser bridge 或 mounted socket 可能重新打开通道。文件只读不能推出网络只读,网络关闭也不能防止对可写 mount 的破坏。

2.4 Plugin/MCP Tool 需要普通策略与 sandbox 策略同时允许

native plugin 与 configured MCP tool 常在 Gateway 一侧执行,不会因为 caller session 在容器里就自动进入同一个隔离环境。为避免 sandboxed turn 借插件绕出容器,OpenClaw 要求普通 effective tool policy 允许它,同时 tools.sandbox.tools 再允许 plugin group、bundle 或具体工具名。

这就是“双门”语义:第一道回答此 Agent/sender 是否可用,第二道回答 sandboxed session 是否可以触达 host-side extension。只在 normal allow 中加名字可能仍看不见;只在 sandbox allow 中加名字也不会越过全局/agent deny。

2.5 workspaceOnly 只检查受控文件工具的路径

tools.fs.workspaceOnly 给 read/write/edit/apply_patch 添加 host path boundary。实现不能只检查字符串前缀:需要解析 relative/absolute、symlink parent、final symlink 与 hardlink alias,避免一个“看起来在 workspace 内”的路径实际写到外面。

即便这些检查完整,workspaceOnly 仍只保护受控文件工具。若 exec 在 host 上可用,shell 可以走自己的 filesystem API;若 plugin 自己接收路径,也要实现相应 guard。container/OS boundary、tool policy 与 library path guard 是 defense in depth,不该用其中一层替代另两层。

会话 permission mode 进一步把受控文件工具限制在记录的 sessionRoot,没有记录时使用目标 Agent 的 canonical workspace。read-only 隐去写入工具并拒绝 exec;guarded 允许根目录内读写,allowlist 未命中时问人;workspace 允许根目录内读写,并把合格 exec 交给自动 reviewer;full 要求 operator.admin。managed worktree 会把根目录固定到 checkout,但创建 worktree 本身不会选择权限模式。它仍不是让任意 shell 自动遵守路径边界的替代品。

三、Host exec 怎样获得许可并防止命令漂移

3.1 Elevated 只改变 sandbox 中 exec 的执行位置

/elevated on 只在当前 session 已 sandboxed 时有意义:它让后续 exec 走 sandbox 外的 configured host path,默认 gateway;若 exec target 已配置为 node,则保持 node。unsandboxed session 的 exec 本来就在 host,elevated 基本是 no-op。

可用性要求 global gate、per-agent gate 和 sender allowlist 全部通过。inline directive 只影响当前消息,session override 次之,global default 最后。缺少任何 gate 时应当显示 unavailable,而不是默默以 host exec 执行。

单独启用 /elevated full 不会获得管理员 full session 的例外:只有合并后的 exec policy 已是 full/off 才跳过审批;普通路径中的 host ask always 仍然要求询问。Elevated 不改变 tool policy,不增加 read/browser/plugin tools,也不能越过 required sandbox。当前 host resolver 允许在没有可用 sandbox 且配置为 auto 时,用明确的 node 请求选择 node;有可用 sandbox 时会拒绝这种显式跨出请求。若配置已固定具体 host,则仍检查请求是否匹配,elevated 不是任意跨主机授权。

3.2 Exec Approval 检查一条具体 host 命令

host exec 先绑定执行计划,再进行所需审核,启动前重新核实计划与策略;变化会在执行前被拒绝
此图聚焦需要审核的普通 host exec:绑定先于审核,复核先于启动。自动审核的资格、管理员 full session 例外以及 node 端绑定范围见正文。

host exec approval 是 Gateway host/node host 的 accidental-execution guardrail。执行条件是 tool policy、elevated gate(sandbox escape 时)、请求的 exec policy、host-local approvals、allowlist 与可能的人类决策共同同意。普通配置路径按更严格的 host policy 合并。显式 full session 则是经过管理员授权的例外:有效 security 仍为 full 时可跳过 host approval-file 下限;turn 只提高 ask 不会恢复这些下限,收紧 security 才会恢复。它仍不能复活被 tool policy deny 的工具,或取消 required sandbox。

这套 approval 不是 per-user auth。Gateway authenticated operator 和 paired node 已经构成 trust relationship;approval 只让具体高风险命令再经过确认。一旦批准,命令仍能按 host filesystem permission 修改任何可达资源。真正的多用户边界仍在 ingress auth、sender policy、Agent isolation 与 OS/sandbox。

当前持久配置入口是 tools.exec.mode,不是把 security/ask 任意组合保存到 session。五种 exec mode 分别是 deny、allowlist、ask、auto 与 full。auto 仅把符合绑定条件的 allowlist miss 送审;reviewer 的 allow 是一次性许可,deny 返回理由,ask 或审核失败才转人工。显式 ask=always 直接要求人工。下面是配置形状,不是对命令安全性的保证:

{ "tools": { "exec": { "mode": "auto", "strictInlineEval": true } } }

自动 reviewer 接收带来源标记、脱敏且有界的对话材料;这些是判断用户意图的证据,不是新的指令。执行器 仍先判断命令是否可绑定;无法完整绑定的 dispatch chain 不会因为模型认为安全就执行。普通配置默认 host exec 为 full,因此不能把“没有配置审批”理解为“默认每条都会询问”。

3.3 Allowlist 绑定 executable,并尽量限制 argv

allowlist 是 per-agent。bare command name 只匹配经 PATH 调用的命令,不匹配 ./rg 或 /tmp/rg;path glob 可限制可信 binary 位置。shell chain 的每个 top-level segment 都要满足规则,不能因为第一段是 git 就顺便放行后面的 curl。

argPattern 能把同一 binary 收窄到特定 argv;approval 生成的 allow-always entry 同时绑定准确 argv 与 cwd。否则允许 python3 就等于允许它读取并执行任意脚本或 inline code。可选的 strictInlineEval 默认关闭;开启后会让 python -c、node -e 等形式即使 binary allowlisted 也继续要求 review/approval。

safe bins 是额外的受限快路径,不应理解为“常见命令天然安全”。stdin-only、参数形态、路径解析和环境都会影响它能否走 fast path。

3.4 审批后的 executable、argv、cwd 与 env 不得漂移

node host 路径先生成 canonical systemRunPlan,审批记录保存 command/cwd/session 等绑定信息。真正转发 system.run 时复用这份 plan,而不是重新相信 caller 后来的字段。若 command、rawCommand、cwd、agentId 或 sessionKey 发生变化,Gateway 拒绝 mismatch。

批准还尽量绑定 resolved executable path,以及 shell script/直接 interpreter 调用中的一个 concrete local file operand。文件在批准与执行之间变更会拒绝;如果无法识别唯一文件,就不伪装成已完整覆盖。best effort 的边界要明确写出,不能把一次点选夸大成对所有 runtime loader 的证明。

审批缺少 UI 或等待超时后走 askFallback,默认 deny。allow once 只对本次 plan,合格的 allow always 生成持久规则,inline-eval 不会成为持久 allow 规则。执行前复核 还会在异步准备之后、真正创建进程之前重读已提交的 host approval policy;撤销可以阻止尚未启动的命令,却不会回滚已运行进程。node 端 executable 绑定覆盖本地策略评估到 dispatch,不能据此声称远端人工等待期间所有 shell 内层 executable 都已完整冻结。

四、怎样诊断安全配置并避免常见误配

4.1 Prompt 与 Skill 提供建议,host code 执行限制

system prompt 可以写“不要执行破坏性命令”,skill 可以要求“先展示 diff 再修改”,它们能显著改善模型选择,但都属于 advisory control。prompt injection、模型错误或错误 skill 仍可能产生危险 call,所以 tool visibility、path guard、sandbox、approval 必须由 host code enforce。

第三方 skill 也应当作 untrusted instruction 审查。它可能诱导模型读取 secret、安装 binary 或打开 elevated;真正的防线是这些动作需要的工具和 host gates仍然受限。第三方 native plugin 风险更高,因为它的代码本就在 Gateway trust boundary 内执行,sandboxed Agent 不会自动隔离插件启动副作用。

4.2 用 explain 与 audit 定位拒绝发生在哪一步

openclaw sandbox explain --session ... 会展示 effective mode/scope/workspace access、是否真的 sandboxed、sandbox tool allow/deny 与 elevated gate。tool policy 过滤会写 agents/tool-policy audit,包含 layer label、key 和受影响工具。

openclaw sandbox explain --session agent:main:main --json
openclaw approvals get --gateway
openclaw exec-policy show
openclaw logs

诊断不要从“把 sandbox 关掉试试”开始。先确认 tool 是否仍在本轮工具列表;若存在,再确认它在 host 还是 sandbox 执行;若是 host exec,继续看 elevated availability、effective exec mode、allowlist 与 pending approval。按这个顺序排查,才能只修改真正拒绝调用的配置。

4.3 六种常见误配及其后果

误配为什么不成立正确边界
deny write/edit,所以 exec 是只读shell 能自行写文件。同时限制 exec,加 sandbox/OS ro。
放进 Docker,所以 plugin 都隔离native plugin 留在 Gateway host。审查安装代码,sandbox policy 双重 gate plugin tool。
approval 通过,所以 sender 有权限approval 是命令同意,不是身份认证。先由 ingress/sender policy 证明 requester。
elevated full 能覆盖 denyelevated 只改变 exec 执行位置/审批。tool policy deny 永远先成立。
workspaceAccess ro,但 bind 默认安全额外 bind 有独立 mode,可能 rw。逐项显式 :ro 并审计敏感 socket/path。
无 UI 时继续执行以免卡住无法确认的请求不应自动放行。askFallback 默认 deny,显式配置例外。

五、八条可以迁移的安全规则

  1. 身份、能力、资源、同意分层。一个 approval 按钮无法代表四者。
  2. Tool policy 决定“有没有”。越权工具先从 schema 消失。
  3. Sandbox 决定“在哪里”。Gateway 与 native plugin 仍在 host。
  4. Approval 绑定“这一条计划”。它不能替代用户认证与 filesystem permission。
  5. Elevated 只为 exec 提供受控 escape。它不是总权限模式。
  6. 区分普通合并与显式授权。普通 exec 受 host 下限约束;管理员授予的 full session 是审批下限的例外,tool deny 与 required sandbox 仍然生效。
  7. 路径与命令都防 TOCTOU。解析 symlink/executable/script,并拒绝批准后的 plan drift。
  8. 说明是软约束,host code 才是硬边界。用 policy、sandbox、OS 和审批做 defense in depth。

下一篇进入多 Agent:当一个 Agent 把工作交给 subagent、ACP harness 或另一段 session 时,权限、workspace、context、结果投递和取消身份怎样继承,哪些状态又必须隔离。

参考源码与文档