许多编码 Agent 都能读文件、改代码、搜索项目、运行测试,甚至执行 shell 命令。
这也是很多人第一次使用它时会有不安的地方:
它能操作 shell,能修改我的本地文件,那它是不是可以在我电脑上为所欲为?
这个问题不能简单回答“是”或“不是”,这里以 Claude Code 为例稍微研究一下。
结论:Claude Code 确实具备操作本地环境的能力,但它也有一套安全边界来约束这些能力。这个边界主要由 权限系统、用户确认、内置工具、Bash sandbox、diff 审查 组成。
这篇文章讨论的范围:macOS 下 Claude Code 原生 sandbox 和权限机制的大致工作方式。
一、为什么 Claude Code 需要 sandbox
Claude Code 不是一个普通聊天窗口,它是一个可以执行工程任务的 Agent。
当你让它“帮我修复登录按钮不生效的问题,并跑一下测试”时,它可能会搜索代码、读取文件、修改组件、执行 npm test,再根据结果继续修复。
这套能力非常有用,但也带来一个问题:只要一个工具能代表你在本机执行操作,它就必须有边界。
对 Agent 来说,风险不只是“删文件”。更常见也更隐蔽的风险包括:读取 .env、SSH key、云厂商 credentials;执行联网命令;修改 package.json scripts、CI、部署脚本;批量修改或删除文件;执行你没有仔细看过的脚本。
所以 Claude Code 需要 sandbox,不是因为它“不可信”,而是因为它真的有行动能力。
二、claude 命令和 bash 的区别
理解 Claude Code sandbox 之前,先要纠正一个常见误解:
claude 不是 bash
Claude Code 是一个 CLI Agent 程序
bash 只是 Claude Code 可以调用的工具之一
你在终端里输入:
claude
进入的不是一个增强版 bash,而是 Claude Code 的交互界面。它背后大概可以这样理解:
用户
↓
Claude Code CLI
├─ 模型交互
├─ 权限判断
├─ Read / Edit / Grep / Glob 等内置工具
└─ Bash 工具
↓
受限或需审批的 shell 命令
Claude Code 本身是一个 Agent Runtime。模型负责理解目标,Claude Code Runtime 负责把下一步翻译成具体工具调用,比如读文件、改文件、搜索代码、执行 Bash 命令。
这里的 Read、Edit、Grep、Glob 可以理解成“参数明确的内置工具”:读哪个文件、改哪个文件、搜什么内容,都能被 Claude Code 用明确参数表达出来。Bash 则是通用 shell 工具,能力更大,风险也更高。
Claude Code 不是“一个会聊天的 bash”,而是“一个能调用 bash 的 Agent Runtime”。
三、普通 bash 的风险来自哪里
普通 bash 的风险不在于 bash 自己有多神秘,而在于它继承了当前用户的系统权限。
例如:
cat ~/.ssh/id_rsa
rm -rf src
curl https://example.com
这些命令看起来是 bash 在执行,但真正读文件、删文件、联网的是操作系统。普通终端里的 bash 通常拥有当前用户的大量权限,所以它能读项目目录,也可能能读 home 目录、配置文件、凭证文件。
如果 Agent 不加限制地调用普通 bash,风险就会被放大。因为 Agent 可能在多轮任务中自动生成命令、自动运行命令;一旦命令里混入高风险操作,或者项目脚本本身被污染,就可能出问题。
所以安全边界不能只依赖“模型应该不会这么做”。
四、macOS 原生 sandbox 如何限制 Bash
Claude Code 的 macOS sandbox,核心作用是限制 Bash 工具及其子进程的文件和网络访问。
在 macOS 上,这类限制基于系统级的 Seatbelt sandbox 机制。可以简单理解为:Claude Code 在执行某些 Bash 命令时,不是直接启动一个拥有完整用户权限的普通 shell,而是把这个 shell 放进一个受限环境。
结构可以简化成:
Claude Code
↓
权限判断 / sandbox 策略判断
↓
macOS Seatbelt sandbox
↓
bash -lc "npm test"
↓
npm / node / 子进程
这和“让模型自觉不要乱来”不是一回事。模型可以提出动作,但真正约束 Bash 的,是操作系统层面的 sandbox。即使 npm test 里启动了 node 脚本、测试框架、子进程,这些子进程也会受到同一套边界影响。
所以关键不是“bash 看起来是不是 bash”,而是“这个 bash 被放在了什么边界里”。
五、sandbox 和权限系统分别管什么
Claude Code 的安全边界不是只靠 sandbox。
更准确地说,它至少有几层:
权限系统:判断工具、路径、命令、域名该不该访问
sandbox:限制 Bash 及其子进程的文件和网络访问
用户确认:决定高风险操作是否继续
diff 审查:确认最终改动是否可接受
这里最容易误解的是:sandbox 主要约束 Bash。
Read、Edit、Write 这类内置文件工具,不是通过 Bash sandbox 运行的,它们主要依赖 Claude Code 的权限系统来约束。Bash 工具则会同时受到权限系统和 sandbox 的影响。
可以用一个公式记住:
允许执行 ≠ 一定执行成功
执行成功 = 应用层允许 + OS 层允许 + 用户没有拒绝
sandbox 本身也不是一个“打开之后所有事情都安全”的万能开关。它还涉及:
- sandbox 内的命令是否自动允许;
- sandbox 内的命令是否仍需确认;
- 命令无法在 sandbox 中运行时,是否允许回退到普通权限流程。
官方文档中的 Auto-allow / Regular permissions,以及 autoAllowBashIfSandboxed、allowUnsandboxedCommands,都可以放在这个框架里理解。
其中最需要谨慎的是非 sandbox 回退:一旦你允许命令脱离 sandbox,它就不再受同一套 OS 级边界限制,而是回到更接近普通终端的执行方式。
权限系统是事前审批,sandbox 是底层兜底。两者应该一起用,但都不能替代人的判断和审查。
六、如何配置 Claude Code 权限
Claude Code 的权限配置,主要解决一个问题:
哪些工具、命令、路径、域名,可以被 Claude Code 使用?
配置通常会有不同层级,比如用户级、项目级、本地级,以及组织统一管控的托管配置。
权限规则大概可以这样理解:
{
"permissions": {
"allow": [
"Bash(npm test*)",
"Bash(npm run lint)",
"Read(src/**)",
"Edit(src/**)"
],
"deny": [
"Read(.env)",
"Read(**/secrets/**)",
"Bash(curl*)",
"Bash(rm -rf*)"
]
}
}
这段不是为了让你直接复制,而是表达一个思路:
- 低风险、高频命令可以 allow;
- 敏感路径和危险命令应该 deny;
- 范围过宽的 Bash 规则要谨慎。
尤其是 Bash 规则,不能只看命令开头。例如:
Bash(npm *)
看起来只是允许 npm,但它可能覆盖很多行为:安装依赖、运行任意 script、执行带生命周期脚本的操作。对团队项目或不熟悉的仓库,这个范围通常太宽。
更好的做法是把高频低风险命令单独列出来:
Bash(npm test*)
Bash(npm run lint)
Bash(npm run build)
七、内置工具和 Bash 工具有什么区别
内置工具和 Bash 的区别可以简单理解为:
Read / Edit / Grep / Glob:内置工具,参数明确,便于权限判断
Bash:通用 shell 工具
常见操作可以这样分:
| 操作 | 优先方式 |
|---|---|
| 读一个明确文件 | Read |
| 修改一个明确文件 | Edit / Patch |
| 搜索代码 | Grep / Glob |
| 跑测试 / 构建 / npm script | Bash |
| 查看 git diff | Bash |
内置工具的行为更明确,权限判断也更直接;Bash 更通用,但一条 shell 命令可能读文件、写文件、联网、启动子进程,所以需要更严格的边界。
八、一次真实操作的安全链路
把前面串起来看,一个真实任务大概是这样。用户说:
帮我修复登录按钮不生效的问题,并跑一下测试。
Claude Code 可能会这样做:
1. Grep 搜索 LoginButton
2. Read 读取相关文件
3. Edit 修改代码
4. Bash 执行 npm test
5. 根据测试结果继续修复
6. 展示最终 diff 和总结
对应的安全链路是:
用户请求
↓
模型决定下一步动作
↓
Claude Code 判断工具和权限
↓
必要时询问用户
↓
Read / Edit / Grep 等内置工具按权限执行
↓
Bash 命令进入 sandbox 或普通权限流程
↓
OS 限制文件和网络访问
↓
结果返回给模型
↓
用户审查 diff / 测试结果
这里面任何一层都不是万能的,但多层机制叠在一起,就比“让模型直接跑普通 bash”安全得多。
九、哪些操作需要特别小心
使用 Claude Code 时,有几类操作要格外注意。
1. 读取敏感文件
.env
.ssh
.npmrc
~/.aws/credentials
secrets
credentials
这些文件里可能有 API key、数据库密码、部署 token、云厂商凭证,建议放进 deny 规则里。
2. 执行联网命令
curl
wget
git clone
npm install
pnpm install
联网本身不是坏事,但它意味着本地环境和外部世界发生了交互。尤其是 npm install、pnpm install,除了下载依赖,还可能触发安装脚本。
3. 修改执行链路
package.json scripts
.github/workflows
Dockerfile
Makefile
husky hooks
部署脚本
这些文件会影响“未来执行什么”。比如 npm test 看起来只是跑测试,但真实执行内容取决于 package.json scripts。
4. 删除或批量修改文件
rm -rf
find ... -delete
sed -i
批量替换脚本
这类操作不是不能做,而是要明确范围。“删掉 dist 目录”和“删掉当前目录下所有匹配文件”,风险完全不同。
十、如何更安全地使用 Claude Code
更安全使用 Claude Code,可以记住这几条:
- 新项目先让它解释计划,不要一上来大范围修改。
.env、.ssh、.npmrc、credentials、secrets 默认 deny。curl、wget、未知安装命令只允许一次,不要永久 allow。- 执行
npm test、npm run build前先看package.json scripts。 - 修改
package.json、CI、部署脚本、hooks 时认真看 diff。 - 保持 Git 工作区干净,方便比较和回滚。
- 团队项目维护项目级权限配置,避免每个人随手点 allow。
十一、总结
Claude Code 不是普通 bash,它是一个 Agent Runtime。
可以这样总结它的安全链路:
模型负责提出动作;
Claude Code 权限系统负责判断动作能不能做;
内置工具负责结构化读写代码;
Bash 工具负责执行项目命令;
macOS Seatbelt sandbox 负责限制 Bash 和子进程不能越界;
用户通过配置、确认和 diff 审查控制最终边界。
Claude Code 的安全性不是建立在“大模型足够听话”上,而是建立在一套受控工具、权限配置和 macOS sandbox 约束之中。
Agent 越有行动能力,就越需要清晰边界。边界不是为了限制效率,而是为了让自动化可以被放心使用。