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 仅允许指定的私有/本地主机(如 localhost10.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 二进制文件

默认情况下,原生运行时通过 /bin/sh 调用命令。将 [runtime].shell 设置为使用其他 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")会被拒绝。运行时启动时会对其进行验证,因此 shell 为空、缺失、不可执行或格式错误时,会快速失败并显示清晰错误,而不会在执行第一个命令时才出错。未设置时默认为 "sh"

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

[runtime]
shell = "pwsh"        # PowerShell 7+   -> pwsh -NoProfile -NonInteractive -Command <cmd>
# shell = "powershell"  # Windows PowerShell 5.x
# shell = "cmd"         # 或留空 -> cmd.exe /C "<cmd>"   (默认)

powershellpwsh(作为通过 PATH 解析的裸名称,或诸如 "C:\\Program Files\\PowerShell\\7\\pwsh.exe" 这样的绝对路径)通过 PowerShell 运行;其他任何值(包括默认的 sh 和显式的 cmd)均通过 cmd.exe /C 运行,与历史行为一致。仅拒绝空值或仅包含空白的值;解释器在启动进程时定位。

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

向模型报告的是同一个运行时选择结果。系统提示中的 ## Runtime 行包含一个 Shell: 字段,用于标明已配置的解释器(bashzshpwshpowershellcmd);当已注册的工具接收模型编写的命令(shellcron_addcron_updateschedule)时,## 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] 配置块。

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 中的 RiskProfileConfigDockerRuntimeConfig