Claude Code 每天安全运行:approval 与 sandbox 的边界怎么划
用「能不能撤销」划清 allow/ask/deny;讲清 plan、acceptEdits、auto、bypassPermissions 怎么换挡,要不要用 dangerously-skip-permissions,以及 sandbox 到底在哪里发力。
「反正每次都会弹确认框,应该出不了事吧。」
刚上手那会儿,我就是这么想的。Claude Code 每做一步都来问一句,我读一眼、点「同意」,自我感觉一直在稳健驾驶。
结果两周后,我盯着自己点鼠标的手,后背一凉:确认文案根本没看,纯靠条件反射在按回车。只要某个操作变成了「老流程」,我就再也没真正确认过它。git push、往外部 API 写数据,我都是没看内容就放行的。没出事,纯属运气好。
确认框不是越多越安全。多了,人就懒得读;少了,连撤不回的操作都顺手放过去。这篇我不抠配置语法的细枝末节,只聊一件事:每天到底该在哪一步停下来。
本文要点
- approval 不是「全拦」也不是「全放」,核心是能撤销的操作走快车道,撤不回的操作故意走慢车道。用「能不能
undo」这一条来划线。 - permission mode(
default/acceptEdits/plan/auto/dontAsk/bypassPermissions)要跟着工作阶段换挡。探索期用plan,边看边改用acceptEdits。 --dangerously-skip-permissions(即bypassPermissions)日常别碰,要减确认就用auto模式或 sandbox。- sandbox 是在操作系统层面收窄 Bash 能碰到的「范围」。它在 macOS / Linux / WSL2 上能跑,原生 Windows 上跑不了。
- 团队里别靠个人自觉,要用 deny 规则和 hooks 把「在哪停」这件事物理地钉死。
至于 settings 文件本身怎么写(Bash(npm run build) 和 Bash(npm*) 差在哪之类),我都放进了姊妹篇 Claude Code 权限配置完全指南;把 CLAUDE.md 和权限组合起来的具体配方,在 CLAUDE.md × 权限配方 里。这篇只专心讲「在哪儿停手」的运营判断。
approval 用「能不能撤销」来划线
划线犹豫不决时,别先纠结技术风险有多大,先问自己一句:
「这事,五分钟后还能撤回吗?」
读文件、grep、看 diff、跑 npm run build——这些做几遍都能重来,最坏也就 git checkout 退回去,所以我希望它们越快越好。反过来,git push、生产环境 deploy、发邮件、往外部数据库写——按下去的那一刻,外面的世界就变了,撤不回。所以这类我故意让它慢。
我平时常用的三档分法是这样的:
| 操作 | 判断 | 理由 |
|---|---|---|
| 浏览、grep、看 diff、build、test、lint | allow | 能撤销,不想拖慢速度 |
| 在分支上改代码 | ask 或 acceptEdits | 看仓库成熟度而定 |
| push、deploy、publish、发邮件、写外部 API | ask | 会影响外面的世界,撤不回 |
读 .env、rm -rf、git reset --hard、curl | sh | deny | 一旦翻车,损失太大 |
这里最让人纠结的是「编辑」这一档。改代码并不是天生危险。一个测试齐全的个人仓库,放手让它快改也不可怕;真正可怕的是在测试薄弱、靠近生产的仓库里对编辑放任不管。所以判断标准不是「要不要允许编辑」,而是改完之后拿什么来验证。验证命令齐备,编辑就可以加速;验证不到位,就老老实实留在 ask。
deny 这一档,「以防万一」多塞几条没坏处。读 .env、各种破坏性命令,从一开始就堵死——反正它们也没有哪天需要升到 allow。我在 危险提示词模式 里举过那种「跳过 permissions 给我用最快的方式」的指令,本质就是专门来拆这道边界的。只要进了 deny,提示词里再怎么花言巧语,本体也会把它拦下来。
permission mode 跟着阶段换挡
如果说 allow/ask/deny 决定的是「拦什么」,那 permission mode 决定的就是「此刻拦多少」——它是挡位。按 Shift+Tab 就能在 default → acceptEdits → plan 之间切换。官方的 permission modes 把所有模式都列全了,但实战里你只要记住下面这张对照表:
| 模式 | 无需确认就放行的范围 | 什么时候用 |
|---|---|---|
default | 仅读取 | 第一次接触的仓库、想稳着来的活 |
plan | 仅读取(只读不改,先出计划) | 想先摸清代码再动手 |
acceptEdits | 读取 + 工作目录内的编辑 | 自己边 review 边改 |
auto | 几乎全部(后台有分类器把关) | 长任务,想少被确认打断 |
dontAsk | 只放行事先 allow 过的 | CI、脚本等封闭环境 |
bypassPermissions | 全部(不做任何检查) | 只在隔离容器 / 虚拟机里 |
我自己的用法很简单:新活的入口一律 plan。先让 Claude 把代码读一遍、把步骤列出来,确认方向对了再动手。方向一旦定下,就落到 acceptEdits 一口气把代码改完,最后用 git diff 集中看结果。比起一行一行点同意,攒到最后一起读反而更专注、更看得进去。这其实就是把「最后一定会看」做成机制——和我在 Harness Engineering 实战指南 里讲的「把守门人交给机器」是同一套思路。
提醒一点:除了 bypassPermissions,其他任何模式下,对 protected paths 的写入都不会自动放行。也就是 .git、.claude、.bashrc、.npmrc 这些——一旦改坏,仓库或配置本身就废了。你在 acceptEdits 下改得正爽,碰到这些地方依然会被叫停。这不是添乱,请把它当成最后一张安全网。
不用 --dangerously-skip-permissions 也能过日子
很多人为了治「确认太多太烦」,伸手就去开 --dangerously-skip-permissions(即 bypassPermissions 模式)。如其名,这是把所有检查一键关掉的开关。
要是把它当成日常对话的常态,那就不再是「有人盯着的 agent」了,只是碰巧还没翻车而已。官方文档也白纸黑字写明这个模式只该用在「隔离的容器 / 虚拟机里」:除了 rm -rf /、rm -rf ~ 这种最极端的情况,它什么都不问;对 prompt injection 的防御也是零。
但「烦」这个感受本身没错。所以该消灭的是确认的数量,不是安全网。替代方案有两个。
一个是 auto 模式。它确实把确认收掉了,但后台有另一个分类器模型在逐条盯着,curl | bash、生产 deploy、往 main 直推、force push 这类危险操作照样会被拦。你在对话里说一句「先别 push」,这句话也会作为一个临时拦截信号生效。确认变少了,危险操作却照停——这和 bypassPermissions 是两码事。不过 auto 模式还处在 research preview 阶段,它不是用来把敏感操作的 review 整个省掉的工具,而是用在「方向上信得过的活」上。
另一个就是 sandbox,下一节专门讲。
想减确认,先上 acceptEdits 或 auto,还不够再上 sandbox;bypassPermissions 就认死它是「容器专用」。按这个顺序想下来,你几乎再也找不到要把安全网整个拆掉的理由了。
sandbox 在操作系统层面锁住「能碰的范围」
如果说 approval 问的是「这个操作能不能做」,那 sandbox 做的是在操作系统层面,直接收窄 Bash 能碰到的文件和网络范围。approval 是「执行前的检查」,sandbox 是「执行中的墙」——它俩在不同的层。
sandbox 厉害的地方,在于它补上了 approval 的短板。approval 是看着命令字符串做判断的,所以 npm run build 在背地里干了点意料之外的事,它察觉不到。但有了 sandbox,这条命令默认就只能写工作目录里的东西。它哪怕没按名字老实干活,操作系统也会从物理上把它摁住。
执行 /sandbox 会弹出设置面板,里头有两种模式可选:
- auto-allow:只要在 sandbox 内,Bash 不弹确认就执行(因为范围被容器圈住了,所以安全)。只有越出范围的操作才退回到平常的 approval。
- regular permissions:哪怕在 sandbox 里,也照常弹确认。控制更紧,但确认也更多。
也就是说,它特别适合「想少点确认、又怕什么都被直接执行」的人。靠范围来兜底,自然就不用一件件去问了。
但有个重要限制:sandbox 只在 macOS / Linux / WSL2 上能跑,原生 Windows 上跑不了。Windows 用户得把 Claude Code 放进 WSL2 里运行。如果用不了 WSL、或者就是要在裸 Windows 上用,那就别指望 sandbox,转而把 allow/ask/deny 分得更严一些:deploy、publish、跟密钥相关的操作尤其要往 ask 上靠。这才是 Windows 下务实的落点。
sandbox 的配置长这样。只对那些「确实需要写到工作目录之外」的工具(比如 kubectl 要碰 ~/.kube),才显式开一个口子:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"sandbox": {
"enabled": true,
"failIfUnavailable": false,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"],
"denyRead": ["~/.aws", "~/.ssh"]
}
}
}
failIfUnavailable: false 的意思是「碰到不支持 sandbox 的环境,就只给个警告、退回普通方式执行」。反过来,如果组织里要把 sandbox 设成强制项,就改成 true,连启动本身都一并拦住。还有个不起眼但很关键的 denyRead:sandbox 默认几乎能读到所有文件,所以像 ~/.aws、~/.ssh 这种密钥目录,显式堵上才安心。
落到「每天的运行」上,配置从哪儿起步
把前面这些判断收进一个文件,日常运行的起点这么写就够了。语法的细节含义(Bash(npm run build) 和 Bash(npm*) 怎么区分之类)我留给 权限配置完全指南:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "plan",
"allow": [
"Read",
"Grep",
"Glob",
"Bash(npm run build)",
"Bash(npm run test)",
"Bash(npm run lint)"
],
"ask": [
"Bash(git push *)",
"Bash(npx wrangler pages deploy *)",
"Bash(node scripts/outreach-send-mails.mjs --send)",
"WebFetch(domain:api.gumroad.com)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Bash(rm -rf *)",
"Bash(git reset --hard *)",
"Bash(curl * | sh)"
]
},
"sandbox": {
"enabled": true,
"failIfUnavailable": false
}
}
它干的就三件事:读取和验证走快车道;会影响外部的操作一律叫停;明显危险的从一开始就禁掉。之所以加了 defaultMode: "plan",是因为我想让每个新会话都从「先读、先计划」开始,之后干着干着再用 Shift+Tab 升到 acceptEdits 就行。
我故意没把编辑(Edit / Write)写进 allow,也没写进 ask——因为我想用模式那一侧(acceptEdits)来管它。如果规则和模式两头都去管编辑,到时候就分不清是哪一边在生效了。编辑交给模式管,外部副作用交给规则管,分清职责,脑子就清爽了。
团队里:把「在哪停」用物理手段钉死
上面说的都是个人的事。一旦成了团队,又多出一个麻烦:每个人的线划在不同地方。有人谨慎,有人就爱开 bypassPermissions 一把梭。一旦靠自觉和良心来约束,那么最松的那个人的玩法,就会变成全队实际生效的下限。
所以,想拦住的地方别交给人来判断,用物理手段钉死。给三个具体例子。
1. 提交前拦住 secret 混入。 用 PreToolUse hook 在 git add 之前机器检查一下 .env 有没有被 stage。不等人反应过来「啊这个不该加进去」,提交就已经被拦下了。
2. deploy 前强制先 build。 别信「我本地 build 应该过了吧」。在 deploy 命令之前挂个 hook,必跑一遍 npm run build。
3. 编辑后自动跑验证。 在 Edit / Write 之后顺手跑 npm run test。哪怕只是改了一点点,验证也会触发,让人没法揣着坏掉的代码往下走。
最小配置大概就这些。hook 不是越多越好,一个「拦截」hook + 一个「验证」hook,这样的运营反而最不容易崩。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git add*)",
"hooks": [{
"type": "command",
"command": "git diff --cached --name-only | grep -E '^\\.env' && echo 'Blocked: .env staged' && exit 1 || exit 0"
}]
},
{
"matcher": "Bash(npx wrangler pages deploy*)",
"hooks": [{
"type": "command",
"command": "npm run build"
}]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "npm run test || true"
}]
}
]
}
}
Windows 上把 grep 那一段换成 findstr 或一段小小的 Node 脚本就能跑。重点不在命令本身,而在「提交前拦截 / deploy 前 build / 编辑后验证」这三个动作的形状。要在组织层面上锁死,还可以用 managed settings 把 bypassPermissions 设成 disable,并把 sandbox 设成强制。真到了团队规模,干脆去 咨询页面 把运营规则连带一起设计,往往才是最快的路。
几个常见翻车
下面三个,都是我或我身边的人实打实踩过的坑。
全塞进 ask,然后心满意足
头一天看着挺安全。可一周后,人就开始不看确认文案直接点同意了。这比 deny 偏弱的状态还危险——因为脑子里会留下「我已经确认过了」的错觉。在罗列 ask 之前,先把 deny 夯实。
--dangerously-skip-permissions 变成口头禅
「哎这下快了」——尝过一次甜头就回不去了。可那只是把监工赶走了而已。嫌确认烦,就用 auto 模式或 sandbox 的 auto-allow。没有任何地方需要你把安全网连根拔掉。
把 build 成功当成发布成功
这个无论做内容运营还是做开发都高频出现。本地 build 明明过了,可线上 URL 还是旧的、只有一种语言没更新、CTA 在手机上排版崩了。approval 和 sandbox 都防不住这种翻车,要靠的是发布之后的核对。我就因为这个,无数次自以为「已经发出去了」。
常见问题
Q. auto 模式和 sandbox 的 auto-allow,到底差在哪?
A. 守法不一样。auto 模式是分类器模型来判断「这操作危不危险」并拦截;sandbox 的 auto-allow 不管操作内容,而是用操作系统把「能碰的范围」锁住来保证安全。前者靠判断来守,后者靠范围来守。两者也可以叠着用。
Q. Windows 上能用 sandbox 吗? A. 原生 Windows 上不行。把 Claude Code 放进 WSL2 里运行就能用。如果就是在裸 Windows 上用,那就别依赖 sandbox,把 deploy、publish、密钥相关的操作往 ask 上靠,并把 deny 设严一些。
Q. plan 模式和 acceptEdits 模式怎么分工?
A. plan 是「只读、不改」,用在摸清代码、把步骤定下来的阶段;acceptEdits 是「工作目录内的编辑不弹确认放行」,用在方向定了、要一口气改的阶段。我都是 plan 起手,达成共识后再落到 acceptEdits。
Q. 进了 deny 的操作,万一就想执行那么一次,怎么办? A. deny 是 Claude Code 本体强制的,提示词没法把它松开(这正是 deny 的价值)。真有需要,就当场去 settings 把它移出来执行,完事再放回去。「临时移出来」这点麻烦本身,就是对危险操作的一脚刹车。
Q. hook 和 permission,职责不会撞车吗? A. 不撞。permission 控制的是「这个操作能不能执行」,hook 控制的是「执行前后必跑什么」。像「拦住 secret 混入」「deploy 前 build」这类确定性的检查,是 hook 的活儿。
我实际试下来的结果
我把这套思路原样塞回了本站的 daily automation。变化最大的,不是 AI 输出质量本身,而是「人到底在哪一步停下来」终于变清晰了。
以前是「随便推进点什么」的含糊运营,有时一次 run 就改改既有文章草草收尾。现在固定成了一条流水线:plan 出步骤 → acceptEdits 改代码 → deploy 前用 hook 跑 build → 发布后用手机把所有语言版本核一遍。自从不再用 bypassPermissions、换成 acceptEdits + sandbox,那种「回过神来发现自己居然往外面动了手」的心头一惊,再没出现过。
比起把一切都甩给聪明的 AI,在撤不回的操作面前先留一口气——看着像绕远路,可真正能让我每天安心地把它跑起来的,是后者。建议你先把 免费 cheatsheet 放在手边,从一行一行填自己的 deny 清单开始。
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
让 Claude Code 真正进入可验证的工作流
先用免费 PDF 固定基础,再用 Gumroad 教材复用工作流;如果涉及团队导入、权限或收入路径,可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
怎么写指令,让 Claude Code 只改一个文件
从一句「改得更好一点」却被动了 40 行的翻车经历,总结出一套把改动范围、验证、回滚打包在一起的 Claude Code 请求模板。
Claude Code 权限拒绝后的恢复流程:不要削弱护栏
把 Claude Code 被拒绝的命令拆成拒绝原因、安全替代步骤、证据命令和重试条件,而不是立刻放宽权限。
Claude Code Harness Smoke Test:信任代理前的15分钟验证循环
用15分钟确认 Claude Code 的范围、禁止区域、验证命令、公开 URL 和收入 CTA。