Claude Code 沙箱相关的报错怎么分流:是沙箱拦的还是权限拦的

2026-08-18
站内工具 AI 编程工具报错分诊器 → 把报错原文贴进去,先分清是网络、额度、配置还是上游故障,再决定往哪个方向查。

开了 sandbox 之后最容易卡住人的场景是这样的:让 Claude 跑个构建或者跑个 git merge,它失败了,你盯着一段报错,不知道该去改 permissions 还是去改 sandbox。改错了地方,配置越加越多,问题还在。

官方文档在《Configure permissions》和《Configure the sandboxed Bash tool》两页里都专门写了一节讲这两层怎么配合。分流的关键在于它们的拦截时机根本不同——时机不同,留下的现象就不同。

先记住时机差:一个在命令跑之前,一个在命令跑起来之后

官方文档《Configure the sandboxed Bash tool》里「Permission rules」一节把这两层的差别写得很直接:

  • 权限规则控制 Claude Code 能不能用某个工具,在任何工具运行之前就被评估,适用于所有工具——Bash、Read、Edit、WebFetch、MCP 等等。
  • sandbox 提供操作系统级的强制,限制 Bash 命令在文件系统和网络上能碰到什么,只作用于 Bash 命令及其子进程

文档接着写明两者执行方式的区别:权限判断在命令运行前基于命令字符串做出,auto mode 下还有一个 classifier 判断这条命令是否安全;而 sandbox 的边界由操作系统施加在正在运行的进程上,所以不管模型选择跑什么、也不管一条被允许的命令实际做的事比它的名字多多少,这个边界都成立。

翻译成排查语言就是一条硬判据:

命令压根没有开始执行 → 权限侧。命令执行了、跑到一半失败 → 沙箱侧。

判定动作一:先看失败输出里有没有沙箱追加的违规细节

这一步最省事,而且文档明确写了这个行为。《Configure the sandboxed Bash tool》的「The unsandboxed retry escape hatch」一节写明:当一条命令因为 sandbox 拒绝其访问而失败时,Claude Code 会把违规细节追加到这条失败命令的输出后面,好让 Claude 看到是哪个文件路径或哪个网络主机被 sandbox 挡了。

所以先翻这条命令的完整输出尾部。有具体路径或主机名的违规细节,基本就锁定在沙箱侧。文档的 Troubleshooting 一节还列了几组特征明显的失败形态,可以当特征串来对:

你看到的现象官方文档给出的原因
命令失败并报 host-not-allowed该 CLI 工具需要访问某个主机,而这个主机不在允许列表里
git merge / git checkoutunable to unlink old它要替换一个 sandbox 拒绝写入的文件;在 Linux 和 WSL2 上这条错误的结尾是 Read-only file system
macOS 上 openosascript 或浏览器登录流报错 -600sandbox 默认阻止 Apple Events
jest 挂住或失败watchman 与 sandbox 不兼容
docker 命令失败docker 与 sandbox 不兼容
在容器里 bubblewrap 起不来非特权容器里 bubblewrap 挂不上一个新的 /proc

这几条的共同点是:命令确实跑起来了,是执行过程中撞了边界。

想看沙箱这一侧当前是什么策略,文档给的动作是运行 /sandbox,在 Config 标签下看解析后的沙箱设置;那些不可豁免的受保护路径,文档说其中大部分也解析在这里,列在 Denied within allowed 之下,和你自己写的 denyWrite 条目混在一起。另外文档里提到两条与沙箱有关的 /doctor 警告,排查时值得顺手跑一下:Sandbox credential injectHosts entries can never match their destination,以及 Sandbox network domain entries have unreliable spellings

判定动作二:命令没跑就被拦,去翻权限规则的来源

如果命令根本没有产生执行痕迹,就去权限侧。文档给的动作是 /permissions:它列出所有权限规则,以及每条规则来自哪个 settings.json 文件。来源这一列在排查中特别有用,因为同一条禁令可能来自 managed settings,而不是你手边这个仓库。

翻规则时按文档写明的顺序读:规则按 deny → ask → allow 求值,第一个匹配决定结果,规则写得多具体并不改变这个顺序。所以像 Bash(aws *) 这样一条宽泛的 deny,会连带挡住同时匹配 Bash(aws s3 ls) 这类更窄 allow 规则的调用——deny 规则没法带例外。ask 与 allow 之间同理:匹配上的 ask 规则照样弹确认。

还有一种更隐蔽的形态:文档写明,裸工具名的 deny 规则(比如就写 Bash)会把这个工具从 Claude 的上下文里整个移除,Claude 根本看不到它;而 Bash(rm *) 这种带范围的规则只是在 Claude 尝试调用时拦下匹配的调用。前者的现象不是”被拒绝”,而是”它压根没试”。

另外,工具名匹配不到任何已知工具的 deny / ask 规则、Bash(command:rm *) 这种试图匹配主内容字段的写法,都会在启动时告警,顺手看一眼能省不少事。

一个高频误判:开了 auto-allow 还是被问,这不是沙箱的锅

这是最容易归错因的一类。文档在 sandbox modes 一节写明,即便在 auto-allow 模式下,显式 deny 规则始终被尊重;针对 /、家目录或其它关键系统路径的 rmrmdir 仍走常规权限流程;像 Bash(git push *) 这种内容作用域的 ask 规则,即使命令是沙箱化运行的也仍然强制弹确认。

还有一条更绕:裸 Bash 的 ask 规则(以及等价的 Bash(*) 形式)对沙箱化运行的命令会被跳过,但对回落到常规权限流程的命令仍然适用;而在 plan mode 下这条跳过不生效,沙箱命令也会被问,包括只读命令。文档同时注明,v2.1.212 之前这个跳过在 plan mode 里也是生效的——典型的口径变更,经验来自更早版本的人很容易把”plan mode 下沙箱命令居然还问我”当成沙箱坏了。

还有一种混合形态:命令先因沙箱失败,然后你被要求确认——这说明两层都碰到了。文档写明,Claude 分析失败后可能dangerouslyDisableSandbox 参数重试;重试的命令在沙箱外运行,因此走常规权限流程,Manual 模式下弹确认,auto mode 下由 classifier 评估底层命令。想在 auto mode 下每次沙箱外重试都被问,文档给的做法是加一条 ask 规则 Bash(dangerouslyDisableSandbox:true)

处置:按落在哪一侧分别改

判定落在沙箱侧,写权限不够就用 sandbox.filesystem.allowWrite 给出具体路径,文档说这比把整个工具从沙箱里排除更可取:

{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "allowWrite": ["~/.kube", "/tmp/build"]
    }
  }
}

这是文档里的原始示例。注意路径前缀的解析规则和权限规则不一样:sandbox 的文件系统路径用常规写法,/tmp/build 就是绝对路径;而 Read 和 Edit 权限规则里 //path 才是绝对路径、/path 是相对于设置来源的。这两套写法长得像,最容易写错。

工具本身与沙箱不兼容的(dockerwatchman 那几类),文档给的是把命令加进 excludedCommands 让它在沙箱外跑,或者按具体条目换用法(jest --no-watchman)。

有一类沙箱拒绝是改不动的:受保护路径。文档写明它覆盖四组路径,包括工作目录及其上层的 .claude 设置文件与 .claude/skills.claude/agents.claude/commands.claude/hooks 目录、.mcp.json 等。文档明确写了没法豁免其中某一条——allowWrite 条目或 Edit allow 规则覆盖到该路径也不解除保护,唯一的关闭方式是 filesystem.disabled,而那会对所有路径关掉文件系统隔离。

顺带说一句容易混的命名:权限系统自己也有一套 protected paths,管的是工具运行之前批准什么;sandbox 那一份管的是已经在运行的命令。名字像,层不同。

判定落在权限侧,处置就是改规则本身:用 /permissions 定位到规则和它的来源文件再动手。如果来源是 managed settings,文档写明其优先级最高,没有任何其它层级(包括命令行参数)能覆盖一条 managed 的权限规则;并且只要一个工具在任意层级被 deny,其它层级都无法再 allow 它。这种情况下改本地设置是白费力气。

处置后怎么验证

沙箱侧有一条明确的验证依据:文档写明,当你在会话过程中编辑这些文件系统列表时,Claude Code 会把改动应用到正在运行的会话,下一条沙箱化命令就按新路径跑。也就是说不必重开会话,重跑原命令即可,再配合 /sandbox 的 Config 标签核对解析后的结果。

一个例外:依赖检查是在启动时跑的,所以在 Linux / WSL2 上装完 bubblewrapsocat 这类包之后要重启 Claude Code,/sandbox 才能检测到。文档写明必需依赖缺失时 Dependencies 会是唯一显示的标签,只缺可选的 seccomp filter 时它与其它标签一起出现;装齐并重启后这个标签就不再出现。

权限侧的验证就是重跑一遍并对照 /permissions 的输出,确认那条规则的来源与你改的文件是同一个。

什么情况说明两个都不是

这一步不能省,因为有几类失败看起来像沙箱,但按文档的机制根本不该由沙箱负责:

  1. 你在原生 Windows 上。 文档写明 sandbox 运行在 macOS、Linux 和 WSL2 上,原生 Windows 不支持;WSL1 也不支持,因为 bubblewrap 需要只有 WSL2 才有的内核特性。而且默认情况下,sandbox 因依赖缺失或平台不支持而起不来时,Claude Code 会显示一个警告然后不带沙箱地运行命令(除非把 sandbox.failIfUnavailable 设为 true,文档说这是给要求把沙箱当作安全闸门的托管部署用的)。所以原生 Windows 上失败,通常要往权限侧或工具本身找。
  2. 出问题的不是 Bash。 文档写明 Read、Edit、Write 这些内建文件工具直接走权限系统,不经过沙箱;MCP 服务器与 hooks 是独立进程,《Choose a sandbox environment》页写明它们在宿主上不受约束地运行。所以 MCP 工具报错、hook 报错都不会是 Bash sandbox 挡的。
  3. 是脚本自己在读写文件。 文档提醒 Read 和 Edit 的 deny 规则适用于内建文件工具以及 Claude Code 能识别的 Bash 文件命令(catheadtailsed 等),但不适用于间接读写文件的任意子进程,比如一个自己打开文件的 Python 或 Node 脚本。
  4. --dangerously-skip-permissions 以 root 身份被拒绝。 这是权限侧的启动检查:文档写明该 flag 在 Linux 和 macOS 上以 root 或经 sudo 运行时会被阻止,在被识别的沙箱内则自动跳过该检查。

Windows 侧单独说

原生 Windows 上没有这个 sandbox,文档给的路径是在 WSL2 里跑 Claude Code,或者用容器 / 虚拟机。确认 WSL 版本的动作,文档写的是在 PowerShell 里跑 wsl -l -v;看到 Sandboxing requires WSL2 就说明这个发行版跑在 WSL1 上,要么升级到 WSL2,要么不带沙箱运行。

WSL2 上有一处专属行为值得记住:启动 cmd.exepowershell.exe/mnt/c/ 下面的 Windows 二进制时,WSL 是通过一个 Unix socket 把这次启动交给 Windows 宿主的,所以一条沙箱化命令能不能启动它,取决于沙箱的 Unix socket 设置——可选的 seccomp filter 必须先装上,才谈得上挡住这个 socket。文档给的两个方向是:用 allowAllUnixSockets 允许这类启动,或把该命令加进 excludedCommands 让它完全不进沙箱。

WSL2 里跑 Ubuntu 24.04 或更新版本的,还有一层 AppArmor:默认策略会阻止 bubblewrap 创建隔离所需的 user namespace。文档给的判定动作是跑 sysctl kernel.apparmor_restrict_unprivileged_userns:返回 0 跳过,报 No such file or directory 说明键不存在、同样跳过,返回 1 才需要为 bwrap 加一份 AppArmor profile。这个现象和权限规则毫无关系,不知道这一层很容易误判成”沙箱配置写错了”。

还有一条纯 Windows 的权限侧行为:文档写明,参数里包含网络(UNC)路径的命令(例如 \\server\share\file)会触发确认提示,因为访问网络路径可能把你的 Windows 凭据发给它指向的主机;同样的检查也适用于 PowerShell 工具的命令。这条属于权限侧,跟沙箱没关系。

上面出现的配置片段与命令均照抄官方文档,未经实测,以官方文档与 --help 的实际输出为准。该产品迭代频繁,命令、配置项与默认值随版本变动,请以官方文档最新内容为准。

最后照搬文档自己写的一句:《Choose a sandbox environment》页明确写着,沙箱隔离降低了被攻破后的影响,但并不消除风险。分流报错是运维问题,别把它当成安全结论。


本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。 该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。 该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。 本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。