Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

沙盒化

运行时可以将工具调用封装在操作系统级别的沙箱中,从而将文件系统访问限制在工作区内,并移除对父进程机密信息的访问权限。这与自治系统和命令允许列表不同:后者是决定工具是否可以运行的_策略_层;而沙箱是_机制_层,用于在工具运行时限制其可以访问的范围。

沙盒设置位于风险配置文件中。每个 agent 通过 agents.<alias>.risk_profile 指向一个风险配置文件;agent 的沙盒启用状态/后端将从该配置文件中读取。

**CLI 模型提供商(例如 grok_cli):**外部 CLI 位于 ZeroClaw 原生工具审批路径之外。上文的风险配置沙箱无法约束它。因此,grok_cli ACP 提供商默认注入 --sandbox strict、--permission-mode dontAsk,并使用空的内置工具集,同时拒绝 ACP 权限请求(当 CLI 提供 reject_once 时选择该选项,否则取消请求)。别名 extra_args 中的显式绕过标志则选择请求的 allow_once 选项;这不会禁用 Grok 已启用的操作系统沙箱,也不会覆盖其拒绝规则。其他权限模式仍会安全失败。请参阅目录 → Grok Build CLI。

sandbox_enabled = false(或 sandbox_backend = "none")会禁用该配置文件额外的操作系统级沙箱封装层。在原生运行时下,这会使工具不具备操作系统沙箱。在 [runtime] kind = "docker" 下,Docker 运行时仍是容器边界,并被报告为 docker-runtime;这些设置会阻止第二个沙箱容器封装运行时自身的 docker run。有关如何将风险配置文件纳入其余配置,请参阅规范的最小可运行示例。

自动检测

sandbox_backend = "auto" 在启动时选择最佳可用后端:

平台首选顺序
LinuxLandlock(内核 5.13+)→ Bubblewrap → Firejail → Docker → 无
macOSSeatbelt(sandbox-exec,原生)→ Docker → 无
WindowsAppContainer(实验性)→ Docker → 无
任何Docker(如果守护进程可达)→ 无

要强制使用特定后端,请将 sandbox_backend 设置为上面列出的字面值之一。

沙箱所限制的内容

文件访问

  • 读取访问权限:仅限于工作区、/usr、/lib、/etc(只读)以及明确列出的额外路径。
  • 写入权限:仅限于工作区和 /tmp。
  • 禁止路径:来自 [risk_profiles.<alias>].forbidden_paths 的绝对组件前缀规则。竞争的允许前缀和拒绝前缀采用最具体匹配优先级,匹配程度相同时拒绝优先;请参阅 Autonomy 路径规则。

网络

默认情况下,沙盒化工具拥有完整的网络出站能力,但不允许入站监听。各后端的注意事项如下:

  • Landlock 不控制网络,它仅作用于文件系统。
  • 配置后,Bubblewrap 和 Firejail 可以阻止网络访问。
  • 当 [runtime].kind = "docker" 时,Docker 容器网络模式遵循 [runtime.docker].network 设置。

特定工具的网络访问控制(browser、HTTP、web_fetch)位于这些工具各自的配置块中([browser].allowed_domains、[http_request].allowed_domains、[web_fetch].allowed_domains)。

对于 http_request,私有/本地目标默认仍处于阻止状态。使用 [http_request].allowed_private_hosts 仅允许指定的私有/本地主机(如 localhost 或 10.0.0.1),同时保持 [http_request].allowed_domains 非空;allowed_domains = [] 仍会禁用请求。现有的 [http_request].allow_private_hosts = true 设置仍作为更宽泛的兼容性选项。

环境

沙箱仅传递 [risk_profiles.<alias>].shell_env_passthrough 中列出的环境变量。继承的密钥除非显式传递,否则不会进入沙箱化的工具。

进程限制

每个工具的实际运行超时设置位于该工具自身的配置块中([shell_tool].timeout_secs 等)。Docker 专属限制(内存、CPU)则位于 [runtime.docker] 中,前提是该代理的运行时类型设置为 docker:

Shell 二进制文件

当未设置 [runtime].shell 时,原生运行时会检测平台默认值。Windows 依次尝试 pwsh、powershell、cmd.exe。macOS 首先使用当前用户 passwd 中配置的登录 shell,然后依次尝试 zsh、bash 和 /bin/sh。Linux 首先使用 passwd 中的登录 shell,然后依次尝试 bash、zsh 和 /bin/sh。Android 固定使用 /system/bin/sh。如需显式选择解释器,请设置 [runtime].shell:

[runtime]
shell = "bash"      # 通过 PATH 解析,或使用绝对路径

在 Unix 上,POSIX 兼容的 shell 通过 <shell> -c "<command>" 调用。powershell/pwsh 在每个受支持的桌面主机上都会选择 PowerShell 语法和策略,并以 <interpreter> -NoProfile -NonInteractive -Command <command> 运行,因此配置文件脚本无法绕过策略重新定义命令,提示也无法阻塞执行。该值必须是在 PATH 中找到的裸命令名(例如 "bash" 或 "pwsh"),或指向可执行文件的绝对路径(例如 "/bin/bash")。配置校验会拒绝空值以及带路径分隔符的相对路径(例如 "./sh"、"bin/sh")。在启动前,ZeroClaw 会直接规范化绝对 shell 路径;若提供了有效的 PATH,则会依据该有效 PATH 解析裸命令名。运行时工厂可能提前解析并保留规范化后的启动器,其他路径则在命令准备期间使用已保留或环境中的解析结果。目标必须是常规可执行文件,否则在运行时构造或命令准备阶段返回失败,不会执行。显式配置优先于默认检测。Unix 登录 shell 的查找使用 getpwuid_r;若其失败或指向不可用的可执行文件,则使用平台回退顺序。若注入的 PATH 缺少所选的裸默认命令,则准备失败,而不会切换到其他解释器。

Firejail、Bubblewrap 和 macOS Seatbelt 会用沙箱启动器替换宿主命令。当请求的 shell 身份与规范可执行文件路径不同时,包装器必须保留该身份(例如,sh 选择 BusyBox applet 或 Bash 兼容模式),同时执行经过验证的规范目标。在 Linux 上,Firejail 和 Bubblewrap 要求宿主进程绝对 PATH 条目中存在支持 --argv0 的 GNU 兼容 env 或 genv。ZeroClaw 会对每个候选程序探测最多两秒;辅助程序及其库必须可在沙箱内访问。在 macOS 上,Seatbelt 使用系统的 /bin/bash 配合固定的 exec -a 跳板,因此不需要单独安装 GNU coreutils。该跳板将请求的身份和命令参数作为进程参数传递,而不是插值为 shell 源代码。ZeroClaw 不会扩大文件系统访问权限,也不会在所需辅助程序无法执行时回退到未沙箱化的命令。Linux 宿主辅助程序查找不使用仅限 TUI 的环境变量覆盖层。

对于这些保留身份的包装启动方式,包含 = 的规范 shell 路径仍会被拒绝;在 Linux 上,env 会将此类操作数解释为环境变量赋值。包含 = 的 Linux 辅助程序路径同样会因相同原因被拒绝,缺失或不受支持的辅助程序会导致准备阶段错误。直接原生执行、Landlock 以及 Docker 独立的容器内 shell 选择都不需要主机身份辅助程序。

在 Windows 上,该值根据其文件名选择解释器系列:

[runtime]
shell = "pwsh"        # PowerShell 7+   -> pwsh -NoProfile -NonInteractive -Command <cmd>
# shell = "powershell"  # Windows PowerShell 5.x
# shell = "cmd"         # 显式 cmd.exe /C "<cmd>"

powershell 和 pwsh(作为通过 PATH 解析的裸名称,或诸如 "C:\\Program Files\\PowerShell\\7\\pwsh.exe" 之类的绝对路径)通过 PowerShell 运行;其他任何显式值均通过 cmd.exe /C 运行,与历史行为保持一致。在 Windows 上,仅拒绝空值或仅包含空白字符的值;解释器在启动时才被定位。

shell 工具、由 shell 支持的技能工具以及 cron/调度 shell 作业都使用此运行时选择。运行时还会将 shell 方言报告给安全策略,因此策略会验证将执行该命令的同一种语言。

向模型报告的是同一个运行时选择结果。系统提示中的 ## Runtime 行包含一个 Shell: 字段,用于标明已配置的解释器(bash、zsh、pwsh、powershell、cmd);当已注册的工具接收模型编写的命令(shell、cron_add、cron_update、schedule)时,## Shell 部分会列出该方言所接受的命令形式,因此模型在 PowerShell 下会编写 Get-ChildItem,在 cmd.exe 下会编写 dir /a,而不是根据操作系统名称进行猜测。两者都来自用于构建命令的同一个适配器,因此报告的 Shell 不会与实际执行的 Shell 发生偏差。无法访问 Shell 的运行时(例如 WASM)会省略这两项。安全部分中的删除建议也会遵循相应的方言:只有在存在 trash 的地方才会建议使用它。

PowerShell 策略接受受限语法:简单命令调用、普通或带引号的参数,以及管道。类似 $PSHOME 和 $PSVersionTable.PSVersion 的简单变量读取仅限于独立的 Write-Output/echo 命令,因此无法向后续命令隐藏文件系统路径。表达式和其他调用形式(包括子表达式、括号、脚本块、类型字面量/静态方法调用、调用运算符、重定向、语句分隔符、反引号转义、$env:NAME 等作用域变量、PowerShell 提供程序路径、直接脚本执行和嵌套命令解释器)均被归类为高风险。仅限 PowerShell 的命令名称不会添加到跨方言默认允许列表中;将所需的 cmdlet 添加到 allowed_commands,或者启用 "*",并配置相应的审批和高风险设置。已知的变更 cmdlet 遵循中/高风险审批门槛;未知的裸命令和 Verb-Noun cmdlet 默认属于高风险。

Cron shell 作业在验证和执行时都会继承全局运行时边界。Native 作业使用配置的原生 shell,而 Docker 作业则通过配置的镜像、挂载、网络、CPU、内存和只读根目录设置运行。cron 条目存储的是命令,而不是复制的运行时或方言。守护进程重新加载并重新创建调度器和工具注册表后,现有作业因此会在下一次运行时使用新加载的 [runtime] 配置。计划的 cron 运行会重新验证,绝不会预先批准。

仅适用于原生运行时类型。Docker 使用其容器的 shell,而 Android(始终为 /system/bin/sh)会忽略此设置,且不会对其进行验证。

各后端的说明

Landlock

Linux 原生路径。零配置,内核强制实施,开销极低。需要内核 5.13 或更高版本。

限制:

  • 无网络限制:Landlock 仅控制文件系统访问。
  • forbidden_paths 是通过基于路径的规则强制执行的,而非基于 inode,因此巧妙构造的符号链接有时可以绕过限制(我们会在交给 Landlock 之前解析链接以缓解此问题)。

Bubblewrap (bwrap)

基于用户命名空间的 Flatpak 沙箱。可限制文件系统访问并阻止网络连接。需要安装 bubblewrap。

Debian/Ubuntu

sudo apt install bubblewrap

Arch

sudo pacman -S bubblewrap

Fedora

sudo dnf install bubblewrap

Firejail

基于 SUID 的沙箱。较旧但广泛可用。

sh

sudo apt install firejail

Firejail 的默认配置文件权限较为宽松;ZeroClaw 会应用自定义配置文件。可在风险配置文件上通过 firejail_args 传递额外参数。

Docker

凡是 Docker 可以运行的地方都能使用。Docker 运行时类型([runtime] kind = "docker")会在临时容器中执行每次 shell 调用;镜像和资源控制请参阅上方的 [runtime.docker] 配置块。git_operations 不在该容器内执行:对于 Docker 运行时,被归类为写操作的 Git 命令会被拒绝,而被归类为读操作的命令仍保留原有的宿主机端读取隔离机制。如需在容器内执行 Git 命令,请使用 shell 工具。

sh

docker build -t zeroclaw-sandbox:local dev/sandbox/   # 构建捆绑的工具包镜像

优点:隔离性强,适用于任何操作系统。缺点:每次调用时容器启动开销较大(100–500 毫秒)。最适合对开销可接受的生产环境部署。

安全带 (macOS)

原生 macOS 沙箱(sandbox-exec)。配置文件采用 SBPL 格式:ZeroClaw 内置了一个用于工具运行。支持 macOS 10.11+。

限制:某些 CLI 工具(较旧版本的 git、部分通过 Homebrew 链接的二进制文件)无法与 Seatbelt 的文件访问规则正常协作。如果你在 macOS 上看到 agent 的 shell 调用返回 “Operation not permitted” 错误,说明该工具需要更广泛的文件系统访问权限:可以考虑改用 Docker。

none

无沙盒机制。工具以 ZeroClaw 服务用户的完整权限运行。这正是 YOLO 模式所启用的特性。明确、显著且有意为之。

故障排除

  • 启动时出现 “Sandbox backend unavailable”:请检查 zeroclaw service status 和 journal 日志;自动检测会记录它尝试过哪些后端。
  • 工具在开发环境正常但在服务中失败:服务用户通常与 CLI 用户不同。请确认两者都拥有所需的沙箱相关权限(Landlock:无;Bubblewrap:启用 userns;Docker:服务用户在 docker 组中)。
  • 在 Docker 运行时上工具调用缓慢:首次调用会拉取镜像,后续调用则很快。可使用 docker pull <image> 预先拉取镜像。

代码参考

  • 检测:crates/zeroclaw-runtime/src/security/detect.rs
  • 后端:crates/zeroclaw-runtime/src/security/sandbox/(每个后端一个文件)
  • 架构:crates/zeroclaw-config/src/schema.rs 中的 RiskProfileConfig 和 DockerRuntimeConfig