帖子说了什么
@madaearly 提醒了一个容易误会的点:在 Claude Code 里打开 /sandbox,并不等于 Claude 碰不到你的密钥。他列了三个常被忽略的缺口:沙箱挡写入和网络,但默认不挡读取;沙箱起不来时默认照样运行命令;命令在沙箱里失败后,Claude 可以申请绕开沙箱重试。
官方文档怎么写
对照官方 Sandboxing 文档,这几条都有明确说明:
- 读取范围:沙箱内的命令默认能读「机器上大部分位置,包括
~/.ssh、~/.aws/credentials这样的凭据文件」;文档还写明没有内置的凭据拦截清单,只有你列出来的文件和环境变量才会被限制。 - 起不来就不拦:如果缺依赖或平台不支持,Claude Code 默认不带沙箱运行命令。原生 Windows 上本来就是无沙箱运行,要用沙箱得进 WSL2。
- 无沙箱重试:命令在沙箱里失败后,Claude 可能带上
dangerouslyDisableSandbox参数重试。谁来批准取决于权限模式:手动模式和acceptEdits会弹出「Bash command (unsandboxed)」提示;bypassPermissions模式直接运行、不提示;如果有一条 allow 规则(比如Bash(curl *))匹配这条命令,也会一并放行重试。
怎么收紧
1. 打开严格模式:在沙箱设置里加 "allowUnsandboxedCommands": false,Claude Code 会忽略 dangerouslyDisableSandbox;再加 "failIfUnavailable": true,沙箱起不来时直接在启动阶段退出,而不是悄悄裸跑。/sandbox 的 Overrides 页把这一项显示为 Strict sandbox mode。
2. 只想多一道确认:如果暂时不想完全禁掉重试,可以加一条 ask 规则 Bash(dangerouslyDisableSandbox:true)。官方说明这条规则在 auto 模式和 bypassPermissions 模式下也会弹提示,而且优先于匹配的 allow 规则。
3. 把凭据列进 sandbox.credentials:
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" }
]
}
}
}
deny 的文件在沙箱里读不到,deny 的环境变量会在每条沙箱命令运行前被清掉。
两个要注意的边界
- 这套配置只管沙箱里的 Bash 命令。内置的 Read 工具、hooks、本地 MCP server 都在沙箱外运行,仍要靠权限规则(例如
Read(~/.ssh/**)的 deny)分别处理;想让所有子进程都拿不到凭据环境变量,官方给的是CLAUDE_CODE_SUBPROCESS_ENV_SCRUB。 - 文档提到,排除项目级设置来源时,项目里的
credentials条目不会生效,用户级~/.claude/settings.json里的deny条目仍然生效。所以凭据拦截最好写在用户级设置里,不要只依赖仓库里的配置。
改完以后,可以让 Claude 在沙箱里试着 cat ~/.ssh/config,确认它确实失败,再开始长时间无人值守的会话。
如果你想让 Claude Code 跑在一台常开、整机独享的新加坡 Mac mini 上,可以了解 Zumac.Ai,咨询 Telegram @singatao。
