Claude Code:第 7 章 权限、安全与撤销

举报
chunkj 发表于 2026/11/08 20:54:08 2026/11/08
【摘要】 Claude Code:第 7 章 权限、安全与撤销摘要:让 AI 直接改磁盘、跑命令,安全边界就成了第一问题。本文讲透六种权限模式的适用场景,规则语法的求值顺序与空格陷阱,沙箱默认不保护哪些目录,以及检查点回滚的能力边界。核心结论只有一句:权限管“能不能做”,检查点管“能不能撤”,两者都不能替代 git。关键词:权限模式;规则语法;沙箱;检查点回滚适用版本:Claude Code 2.1...

Claude Code:第 7 章 权限、安全与撤销

摘要:让 AI 直接改磁盘、跑命令,安全边界就成了第一问题。本文讲透六种权限模式的适用场景,规则语法的求值顺序与空格陷阱,沙箱默认不保护哪些目录,以及检查点回滚的能力边界。核心结论只有一句:权限管“能不能做”,检查点管“能不能撤”,两者都不能替代 git。

关键词:权限模式;规则语法;沙箱;检查点回滚

适用版本:Claude Code 2.1.x | 文中参数、配额与价格随版本变化,以官方最新说明为准


7.1 两层安全机制

Claude Code 有两个互不替代的机制:

机制 管什么 能撤吗
权限(permissions) 做之前要不要问你 —
检查点(checkpoints) 做了之后能不能撤销文件改动 能,但只管文件

只有权限能防止「不该发生的事」。检查点不能替代 git。


7.2 六种权限模式

📘 官方:权限模式决定「哪些动作不用问你就能做」。

模式 配置值 不用问就能做 适合
Manual default 只读 逐条审阅、敏感工作
Accept edits acceptEdits 读、改文件、常见文件系统命令(mkdir touch rm rmdir mv cp sed) 边改边审代码
Plan plan 读;auto 模式可用时还有分类器批准的命令 改代码前先探索
Auto auto 全部,但后台分类器检查 长任务、减少弹窗疲劳
Don’t ask dontAsk 工作目录内的文件读取 + 预批准的工具;其余一律拒绝 锁定的 CI / 脚本
Bypass bypassPermissions 全部 仅限隔离容器/虚拟机

🔍 补充细节:default 在 CLI、--help、VS Code、JetBrains、桌面端里都显示为 Manual。配置值仍是 default(hooks 和 SDK 用这个),CLI 也接受 manual 作为别名。

切换

CLI 里按 Shift+Tab 循环:

auto → default → acceptEdits → plan →(可选模式)→ auto

状态栏会显示 ⏸ manual mode on、⏵⏵ accept edits on、⏸ plan mode on、⏵⏵ auto mode on、⏵⏵ don't ask on、⏵⏵ bypass permissions on。

不是所有模式都在循环里:

模式 什么时候进循环
auto 自动模式可用时
bypassPermissions 你先用 --permission-mode bypassPermissions、--dangerously-skip-permissions、--allow-dangerously-skip-permissions 启动,或在用户/--settings/managed settings 里设了 defaultMode
dontAsk 永远不在循环里,只能 --permission-mode dontAsk

--allow-dangerously-skip-permissions 的特殊之处:把模式加进循环但不激活它。

启动时的模式(决定顺序)

新会话按下面顺序取第一个生效的:

  1. --permission-mode 或 --dangerously-skip-permissions
  2. settings 文件里的 permissions.defaultMode
  3. 内置默认

内置默认:

情况 默认模式
任何 settings 文件设了 disableAutoMode: "disable" default
claude -p 或 Agent SDK default
组织启用了 HIPAA 配置且会话符合条件 default(auto 仍可切过去)
终端会话 / VS Code 扩展 auto(v2.1.283+;更早版本仅 Pro/Max/Team)

⚠️ 踩坑提醒(高频困惑):

  • 在 .claude/settings.json 或 .claude/settings.local.json 里写 "defaultMode": "auto" 不生效——项目级文件里的 auto 会被忽略,回落到内置默认。要设 auto 就写在 ~/.claude/settings.json。
  • 在项目级文件里写 "defaultMode": "bypassPermissions" 也不生效,会话会以 Manual 启动。
// ~/.claude/settings.json
{
  "permissions": { "defaultMode": "default" }
}

🔍 补充细节:很多人抱怨「我明明设了 default 怎么还是 auto」——很可能是设在了项目文件里,或者优先级被 managed settings 覆盖。用 /status 和 /permissions 核对实际生效值。


7.3 哪些动作任何模式都不会自动批准

📘 官方:即使在 bypassPermissions 下,下面这些也不会自动放行:

  • 被显式 ask 规则匹配的工具
  • 组织把 connector 工具设为 ask 的
  • 需要用户交互的工具:AskUserQuestion、标了 requiresUserInteraction 的 MCP 工具
  • 被识别为关键路径的 rm / rmdir(如 rm -rf /、rm -rf ~)——任何 allow 规则或 PreToolUse hook 的 "allow" 都批准不了
  • 跨会话消息的安全保护
  • 开了 permissions.blockReadsOutsideWorkingDirectories 时,工作目录外的读取

受保护路径(protected paths)

.git、.claude 这类路径的写入永不自动批准——除非在 bypassPermissions 模式,或者在有 bypass 可用的交互式终端里处于 plan mode。


7.4 权限规则语法

规则格式是 Tool 或 Tool(说明符)。

基本形态

规则 效果
Bash 所有 Bash 命令
Bash(*) 同上
Read 所有文件读取
WebFetch 所有网页抓取
Bash(npm run build) 精确匹配这一条命令
Bash(npm run *) npm run 开头的所有命令
Read(./.env) 读当前目录的 .env
WebFetch(domain:示例域名) 抓取示例域名
mcp__* 所有 MCP 工具(仅 deny/ask 可用)
mcp__puppeteer__* puppeteer 服务器的所有工具(allow 里也可用)

🔍 补充细节:作为 deny 规则的裸工具名(如 Bash)会把工具从 Claude 的上下文里彻底移除——它根本看不到这个工具。带说明符的规则(Bash(rm *))则保留工具,只是在调用时才拦。这个区别在排查「它怎么不用某个工具」时很有用。

求值顺序(背下来)

📘 官方:deny → ask → allow。按这个顺序取第一个匹配,规则的具体程度不影响顺序。

含义很关键:

  • Bash(aws *)(deny)+ Bash(aws s3 ls)(allow)→ aws 全部被禁,allow 无法「开洞」
  • Bash(git push *)(ask)+ 更宽的 allow → 仍然会提示

通配符的三个匹配规则

📘 官方:

  1. * 代替它所在位置的任意文本。 在 Bash(git * main) 里它代替子命令,所以匹配所有 git 子命令和之前的选项(包括 -c);在 Bash(* --version) 里它代替程序名。
  2. 结尾的 * 且前面有空格时,也匹配裸命令。 Bash(ls *) 匹配 ls;但前提是这个结尾 * 是规则里唯一的通配符——Bash(* --help *) 匹配 npm --help x 但不匹配 npm --help。
  3. 结尾 * 前面的空格是规则的一部分。 Bash(ls *) 要求 ls 后有空格,所以不匹配 lsof;Bash(ls*) 没有空格,匹配 lsof。
你写的 匹配 不匹配
Bash(npm run build) npm run build npm run build --watch
Bash(npm run *) npm run build、npm run test --watch、npm run npm install
Bash(git log * main) git log --oneline main、git log -5 main git log main、git push origin main
Bash(git * main) git merge main、git push origin main git log
Bash(* --version) node --version、bash -c 'echo hi' --version node -v
Bash(ls *) ls -la、ls lsof
Bash(ls*) ls -la、lsof
Bash(* --help *) npm --help x npm --help

⚠️ 踩坑提醒:* 要放在子命令之后。git log --oneline main 里 git 是程序、log 是子命令。Bash(git *) 放行所有 git 命令;Bash(git * main) 会在启动时警告「通配符放在了子命令前面」,因为它放得太宽。

Bash(ls:*) 与 Bash(ls *) 等价。但 :* 只在结尾才被识别;Bash(git:* push) 里的冒号是字面字符,匹配不到任何 git 命令。

按输入参数匹配(deny / ask 专用)

{
  "permissions": {
    "ask": [
      "Agent(model:opus)",
      "Bash(run_in_background:true)",
      "Bash(dangerouslyDisableSandbox:true)"
    ]
  }
}

规则:

  • 参数必须是工具输入的直接字段,嵌套在对象/数组里的不行
  • 一条规则只写一个参数;要同时卡 model 和 isolation 就写两条
  • 值支持 * 通配,不写 * 就是精确匹配
  • 模型省略的参数永远不匹配(Agent(model:*) 不匹配没设 model 的调用)
  • 值跟 Claude 实际发送的字面值比较,不做归一化(Agent(model:opus) 匹配别名 opus,不匹配完整模型 ID)
  • 不能用这种方式匹配工具的主要内容字段:Bash 的 command、Read/Edit/Write 的 file_path、Grep/Glob 的 path、WebFetch 的 url。Bash(command:rm *) 会被忽略并给启动警告——用 Bash(rm *) 代替

完整配置示例

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git commit *)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Edit",
      "Read"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Read(./.env)",
      "Read(./secrets/**)",
      "WebFetch(domain:evil.example)"
    ],
    "defaultMode": "acceptEdits",
    "additionalDirectories": ["../shared-lib"]
  }
}

「Yes, and don’t ask again」保存在哪

📘 官方:Bash 命令和 WebFetch 域名的永久批准会写进仓库根目录的 .claude/settings.local.json(通过 worktree 解析到主检出),对该仓库任何位置的后续会话生效。

文件修改的批准不落盘,只在本次会话内有效。


7.5 管理权限:/permissions

/permissions

这个对话框列出所有规则以及每条规则来自哪个 settings 文件。Claude 干活时也能打开;增删规则会从下一次工具调用就生效。

🔍 补充细节:排查「为什么它问了我一个我以为已经放行的命令」时,/permissions 是唯一能看清全貌的地方——包括项目级、用户级、managed 各层的规则。

给权限提示加备注

在大多数权限提示上,移到 Yes 或 No 按 Tab 打开备注框:

  • Enter 提交答案并附备注
  • Tab 关闭备注框但不作答
  • 选 Yes → 执行后把备注发给 Claude
  • 选 No → 备注作为拒绝原因发给 Claude,它继续工作

🔍 补充细节:这是个被忽略的高效技巧。拒绝时写「不要动 migrations 目录,改 config/ 下的 schema」比直接按 No 有用得多。


7.6 Auto 模式:让分类器替你值班

它做什么

📘 官方:一个单独的分类器模型在动作执行前审查,拦截三类:超出你请求范围的升级、针对未识别基础设施的动作、由它读到的敌意内容驱动的动作。

默认会被拦的典型动作(节选):

  • 下载并执行代码(curl | bash)
  • 把敏感数据发到外部端点
  • 生产环境部署 / 迁移
  • 云存储上的批量删除
  • 授予 IAM 或仓库权限
  • 修改共享基础设施
  • 销毁会话开始前就存在的文件
  • force push
  • 提交或推送会泄露密钥/敏感数据的改动
  • git reset --hard、git checkout -- .、git restore .、git clean -fd、git stash drop/clear
  • 修改不是本会话创建的 HEAD 提交(--amend)
  • terraform destroy / pulumi destroy / cdk destroy / terragrunt destroy
  • 写 secret manager、改 DNS / TLS 证书
  • 合并未经人工批准的 PR、批准 Claude 自己的 PR、关闭 CI 检查
  • 开关/删除生产 feature flag
  • 打印真实凭证到对话或文件
  • 绕过内部包仓库走公共源
  • 用 --insecure 之类关闭安全护栏的参数
  • 启动无人审批、无沙箱的自治循环(比如带 --dangerously-skip-permissions 的进程)
  • 通配符 / glob / 按时间删除 /tmp、$TMPDIR 等共享临时目录里的文件
  • 把敏感细节写进发给他人的内容(PR 正文、issue、提交信息、评论)
  • 注释掉、删除或强行通过保护安全行为的测试/断言
  • 把 API base URL、代理端点、webhook、registry 镜像改为第三方主机
  • 改动 push 去向(git remote set-url / git remote add),除非你点名了新 remote
  • 向已知公开的仓库推送密钥或个人数据
  • 向 Claude Code 自己的 tmux pane 发送按键(视为改自己的权限)

默认放行的典型动作:

  • 工作目录内的本地文件操作
  • 安装 lock 文件 / manifest 里声明的依赖
  • 读 .env 并把凭证发给它对应的 API
  • 只读 HTTP 请求
  • 向你正在工作的这个仓库的任意分支 push(包括默认分支)——除非分支名表明它是部署/发布目标,如 production、gh-pages
  • 删除本会话自己创建的那些 job
  • 为完成任务而读写安全相关代码、配置、威胁模型
  • 同一个多代理会话内代理之间的消息
  • 发数据到你在 environment 里列出的可信域名/桶/服务
  • 在 Chrome 里导航到可信内网域名、本地主机、或你点名的 URL

⚠️ 踩坑提醒:auto 模式降低弹窗,不保证安全。官方原话:“Use it for tasks where you trust the general direction, not as a replacement for review on sensitive operations.”

可用条件

维度 要求
套餐 所有套餐
组织 Team/Enterprise 默认可用;管理员可用 disableAutoMode: "disable" 关掉
模型(Anthropic API、Claude Platform on AWS) Opus 4.6+、Sonnet 4.6+、Haiku 5.5、Fable 系列
模型(Bedrock / Google Cloud / Foundry / 已登录网关) 只有 Sonnet 5+、Opus 4.7+、Haiku 5.5、Fable 系列
不支持的模型 Sonnet 4.5、Opus 4.5、Haiku 4.5、claude-3 系列

出问题时

  • 报「auto mode unavailable」→ 先查上面的条件,再查有没有 settings 文件设了 disableAutoMode
  • 报某个动作「cannot determine the safety」→ 分类器请求失败。通常是暂时的;在 Bedrock 上可能是账号还调不了指定的分类器模型

查看默认规则

claude auto-mode defaults

以 JSON 打印完整的规则列表。经常被误拦的话,管理员可以用 autoMode.environment 加可信仓库/桶/服务(见 Configure auto mode)。

用 ask 规则加人工检查点

auto 模式下想在某些命令前停一下(比如 push):

{
  "permissions": {
    "ask": ["Bash(git push *)"]
  }
}

📘 官方:ask 规则按命令字面形式匹配,所以 git -C . push 这种写法不受约束。


7.7 沙箱:操作系统级的边界

它是什么

📘 官方:Bash 沙箱是操作系统强制的边界,包住 Claude 在你机器上运行的 shell 命令。你设定这些命令能碰哪些文件、能访问哪些网络域名;限制在命令运行期间由系统施加。

覆盖 Bash、PowerShell、Monitor 命令以及它们启动的进程。只覆盖 shell 命令——Claude 的文件工具、MCP 服务器、hooks 在沙箱之外运行。

平台:macOS(Seatbelt)、Linux、WSL2。原生 Windows 不支持——要在 Windows 上用沙箱,在 WSL2 里跑 Claude Code。

默认边界

访问 默认
写 工作目录、每用户临时目录、你添加的目录;受保护路径仍然禁止写
读 机器的大部分,包括 ~/.ssh、~/.aws/credentials 这类凭证文件
网络 没有直接出口。连接走本机代理逐 host 校验允许域名,允许列表初始为空
环境变量 从 Claude Code 继承,包括它环境里的密钥

⚠️ 踩坑提醒(重要):默认配置下沙箱不会保护你的 SSH 私钥和云凭证。要保护它们读 sandbox.credentials 设置(见 7.7 末尾)。

开启

/sandbox

Linux / WSL2 需要 bubblewrap 和 socat。mac 直接可用。/sandbox 面板会告诉你缺什么。

或在设置里:

{ "sandbox": { "enabled": true } }

两种沙箱模式

模式 行为
Auto-allow 命令在沙箱内跑 → 自动批准,不弹窗;因为匹配 excludedCommands 或走了非沙箱重试而在沙箱外跑 → 走正常权限流程
Regular permissions 所有 Bash 命令都走正常权限流程,即使在沙箱内

Auto-allow 下仍然生效的:

  • 匹配 Bash deny 规则的命令仍被拦
  • 针对关键路径的 rm / rmdir 仍走权限流程
  • 内容型 ask 规则(如 Bash(git push *))仍强制提示
  • 裸 Bash ask 规则(或 Bash(*))对沙箱内命令跳过,对沙箱外命令仍生效;但在 plan mode 下不跳过
  • Monitor 工具命令不自动批准(虽然仍在沙箱内跑)

🔍 补充细节:auto-allow 与你的权限模式独立工作。即使你在 Manual 模式,开了 auto-allow 之后沙箱内的 Bash 命令也会自动执行。这是「安全 + 不烦人」的最佳组合之一。

非沙箱重试(逃生舱)

沙箱挡住网络连接时,结果里会写明被拒的 host,Claude 看到后可能用 dangerouslyDisableSandbox 参数重试。

谁批准这次重试:

模式 行为
bypassPermissions 不问,直接跑
Manual / acceptEdits 弹出 “Bash command (unsandboxed)” 提示
auto 另一个分类器评估底层命令
dontAsk 拒绝
plan 见官方 plan mode 说明

想强制「绝不逃逸」:

{
  "sandbox": {
    "allowUnsandboxedCommands": false,
    "failIfUnavailable": true
  }
}

这就是 /sandbox 里的 Strict sandbox mode。

保护凭证

{
  "sandbox": {
    "credentials": {
      "files": [
        { "path": "~/.ssh", "mode": "deny" },
        { "path": "~/.aws/credentials", "mode": "deny" }
      ]
    }
  }
}

🔍 补充细节:具体字段名以 settings reference 的 sandbox 一节为准。核心思路是:默认读权限很宽,必须显式 deny 才安全。

让某些命令走沙箱外

{
  "sandbox": {
    "excludedCommands": ["docker *"]
  }
}

7.8 工作目录

什么是工作目录

你在哪个目录启动 claude,它就是工作目录。只读工具默认只能碰这里。

加目录

claude --add-dir ../shared-lib

或写进设置:

{
  "permissions": {
    "additionalDirectories": ["../shared-lib"]
  }
}

📘 官方:additional directories 只授予文件访问权,不授予配置。别指望在 ../shared-lib/.claude/settings.json 里的规则会生效。

切换会话目录

会话中途可以用 /add-dir(或对应命令)扩展。


7.9 检查点与回滚

什么时候创建

📘 官方:每次你发送一个开启新回合的提示词时,Claude Code 捕获代码状态。会话内保留最近 100 个检查点的快照。

检查点随会话一起保存,所以恢复会话后仍能 /rewind。

打开回滚菜单

  • /rewind
  • 输入框为空时按两次 Esc

⚠️ 踩坑提醒:输入框里有文字时,双击 Esc 是清空输入,不是打开菜单。清掉的内容存进历史,↑ 可以找回。

六个选项

选项 效果
Restore code and conversation 代码和对话都回到那个点
Restore conversation 只回滚对话,保留当前代码
Restore code 只回滚文件,保留对话
Summarize from here 从这个点往后压缩成摘要
Summarize up to here 这个点之前的压缩成摘要,后面的消息原样保留
Never mind 什么也不做,返回列表

两个 restore code 选项只在选中的检查点有可回滚的文件改动时出现。

引导摘要

高亮某个 Summarize 选项后,在 add context (optional) 处直接输入指令再按 Enter:

保留所有改动过的文件列表和测试命令

按数字键则直接总结、不带指令。

局限(必须知道)

局限 说明
Bash 命令的改动 只有 Claude 用文件工具改过的文件,之后被 Bash 改才能回滚。只被 Bash 改过的文件不追踪
子代理的改动 通常不捕获。前台 fork 的 skill 例外(context: fork + background: false)
外部改动 你在 Claude Code 之外手动改的、其他并发会话改的,不追踪
回合中途发的消息 后排队进来的消息没有自己的检查点,标记为 No code restore;回滚要选「开启该回合的那条提示词」
符号链接/硬链接 不会恢复,会提示 Restored the code, but skipped N files。dotfile 管理器软链进来的配置、pnpm 硬链进来的包都属此类
30 天后 快照随会话保留期被清掉,回滚会报 No files were restored。想留久点就调大 cleanupPeriodDays

⚠️ 踩坑提醒:rm -rf 删掉的文件、数据库迁移、git push 到远端——这些都不是文件快照能救的。它们只能靠权限模式、ask 规则和你自己。

回滚不是版本控制

📘 官方:检查点是为会话级快速恢复设计的。永久的版本历史和协作,继续用 git。


7.10 安全实践清单

日常

  • ☐ 在项目根目录启动,不在 ~ 里启动
  • ☐ 用 auto 模式做「方向可信」的任务,敏感操作切回 Manual
  • ☐ 给 git push、rm -rf、terraform destroy 加 ask 规则
  • ☐ 把 .env、secrets/、~/.ssh 加进 deny 读规则
  • ☐ 开沙箱 + auto-allow,兼顾安全和效率
  • ☐ 明确 deny 掉 ~/.ssh、~/.aws/credentials 的沙箱读权限

无人值守

  • ☐ claude -p 用 --permission-mode dontAsk + 精确的 --allowedTools
  • ☐ 或用 --permission-mode auto
  • ☐ 只在容器/VM 里用 --dangerously-skip-permissions
  • ☐ 容器里以非 root 用户运行

关于 Claude 的承诺

📘 官方:权限规则由 Claude Code 强制执行,不是模型。你在提示词或 CLAUDE.md 里写的指令会影响它「想做什么」,但不会改变 Claude Code 允许什么。

这句话很重要:别指望在 CLAUDE.md 里写「永远不要删文件」来获得安全保障。 那是建议,不是约束。要硬约束就用 deny 规则或 hook。


7.11 小结

  • 权限管「能不能做」,检查点管「能不能撤」,都不能替代 git
  • 六种模式:default / acceptEdits / plan / auto / dontAsk / bypassPermissions
  • 规则求值顺序 deny → ask → allow,具体程度不影响顺序
  • Bash(ls *) 不匹配 lsof;Bash(ls*) 匹配。结尾 * 前的空格是规则的一部分
  • 项目级设置里的 auto 和 bypassPermissions 不生效,要写用户级
  • auto 模式靠分类器,降低弹窗但不保证安全
  • 沙箱默认不保护 ~/.ssh 和云凭证,要显式 deny
  • 回滚只管文件工具改过的文件;Bash 改的、子代理改的、外部的都不管

下一步 → 第 8 章《CLAUDE.md 与记忆》

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。