Tips & Tricks (更新: 2026/6/7)

Claude Code 每天安全运行:approval 与 sandbox 的边界怎么划

用「能不能撤销」划清 allow/ask/deny;讲清 plan、acceptEdits、auto、bypassPermissions 怎么换挡,要不要用 dangerously-skip-permissions,以及 sandbox 到底在哪里发力。

Claude Code 每天安全运行:approval 与 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、lintallow能撤销,不想拖慢速度
在分支上改代码ask 或 acceptEdits看仓库成熟度而定
push、deploy、publish、发邮件、写外部 APIask会影响外面的世界,撤不回
.envrm -rfgit reset --hardcurl | shdeny一旦翻车,损失太大

这里最让人纠结的是「编辑」这一档。改代码并不是天生危险。一个测试齐全的个人仓库,放手让它快改也不可怕;真正可怕的是在测试薄弱、靠近生产的仓库里对编辑放任不管。所以判断标准不是「要不要允许编辑」,而是改完之后拿什么来验证。验证命令齐备,编辑就可以加速;验证不到位,就老老实实留在 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,下一节专门讲。

想减确认,先上 acceptEditsauto,还不够再上 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 清单开始。

#claude-code #permissions #approval #sandbox #security #workflow
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

让 Claude Code 真正进入可验证的工作流

先用免费 PDF 固定基础,再用 Gumroad 教材复用工作流;如果涉及团队导入、权限或收入路径,可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。