<!-- title: 权限系统与配置入门实战 -->

# Claude Code 权限系统与配置入门：从白名单到安全放行全实战

## 概述

本教程面向已经完成 Claude Code 安装、能跑通首个项目，但每次操作都被反复弹窗"Allow / Deny"困扰的开发者。你将系统掌握 Claude Code 的权限判定机制、`settings.json` 四层作用域、`allow / ask / deny` 规则语法、六种权限模式，以及如何用一条"白名单 + 兜底拒绝"策略把日常开发中的确认弹窗降到接近零，同时把 `rm -rf`、`git push`、`.env` 泄露等高危操作牢牢锁死。学完即可为团队产出一份可直接提交到 Git 的安全配置文件。

## 前置条件

- 已安装 Claude Code（原生安装或 npm 安装均可），能在终端启动并完成一次对话。
- 了解基本命令行操作（`cd`、`ls`、`git`）。
- 有一个用于练习的代码仓库目录（建议新建空目录，避免误伤现有项目）。
- 文本编辑器查看 / 编辑 JSON 文件。

## 第一步：理解权限系统的三层分级

Claude Code 的权限并非"一刀切开关"，而是按工具类型分级处理，这是理解整个体系的基石：

| 工具类型 | 示例 | 是否需要审批 | "Yes, don't ask again" 的生效范围 |
| --- | --- | --- | --- |
| 只读工具 | 文件读取、Grep、Glob | 否 | 不适用 |
| Bash 命令 | `npm run build`、`git commit` | 是 | 按"项目目录 + 命令前缀"永久记住 |
| 文件修改 | Edit / Write | 是 | 仅在当前会话内有效 |

这条分级规则解释了一个常见困惑：为什么 `cat`、`ls` 从来不弹窗，而 `npm install` 每次都要确认。原因是 Claude Code 内置了一批"只读命令白名单"，包括 `ls`、`cat`、`echo`、`pwd`、`head`、`tail`、`grep`、`find`、`wc`、`which`、`diff`、`stat`、`du`、`cd`，以及 `git` 的只读形态（如 `git status`、`git log`）。这套只读集合**不可配置**——如果你想强制让 `cat` 也弹窗，必须显式写一条 `ask` 或 `deny` 规则。

**操作说明**：在练习目录中启动 Claude Code，依次输入"看一下当前目录结构""读一下 package.json"等指令，观察这些只读操作零弹窗；再输入"运行 npm install"，观察弹出审批框。

**预期结果**：只读操作直接执行；写操作弹出审批，点击 "Yes, don't ask again" 后，该命令前缀在本目录内不再询问。

**常见问题**：有用户误以为"只读命令白名单"可以被关掉来提升安全。事实上它只是省略了交互确认，底层仍是受控的只读行为；真正的安全闸门在于 `deny` 规则与权限模式，而非禁用只读集合。

## 第二步：认清 `settings.json` 的四层作用域

Claude Code 用"作用域（scope）"机制决定配置在哪里生效、与谁共享。从高到低优先级依次是：

| 作用域 | 文件位置 | 影响范围 | 是否随 Git 共享 |
| --- | --- | --- | --- |
| Managed（托管） | 服务端下发 / 系统级 `managed-settings.json` | 本机所有用户 | 由 IT 统一部署 |
| User（用户） | `~/.claude/settings.json` | 你自己的所有项目 | 否 |
| Project（项目） | `<repo>/.claude/settings.json` | 本仓库所有协作者 | 是（提交到 Git） |
| Local（本地） | `<repo>/.claude/settings.local.json` | 仅你在本仓库 | 否（自动 gitignore） |

需要特别记住一条**反直觉规则**：普通配置项按"高优先级覆盖低优先级"合并（Managed 最高、User 最低），但**权限规则是跨作用域"合并"而非"覆盖"**。也就是说，User 作用域里允许的 `Bash(npm run *)`，在 Project 作用域里依然有效，二者叠加生效。

**操作说明**：用 `/config` 命令打开设置面板，可以一览当前生效的所有配置及其来源作用域；用 `/permissions` 命令则专门查看权限规则列表，并标注每条规则来自哪个 `settings.json`。

**何时用哪个作用域**：
- 团队共享的权限策略、Hooks、MCP 服务器 → 写进 Project 作用域并提交 Git。
- 个人偏好（主题、编辑器、个人 API Key）→ 写进 User 作用域。
- 临时试验、机器相关路径 → 写进 Local 作用域，避免污染团队仓库。
- 安全合规、不可被覆盖的强制策略 → 由 IT 写进 Managed 作用域。

**常见问题**：很多人手写 `.claude/settings.local.json` 后忘记加 `.gitignore`，把本地绝对路径误提交。最佳实践是让 Claude Code 自己创建该文件（创建时会自动配置 gitignore），或手动补上忽略规则。

## 第三步：掌握 `allow / ask / deny` 规则语法

权限规则的格式非常简洁：`Tool` 或 `Tool(specifier)`。三类规则的核心差异在于**评估顺序**：

> **deny → ask → allow**，按此顺序逐一匹配，**第一条命中即决定结果**，规则的"具体程度"不会改变这个顺序。

这意味着一条匹配的 `ask` 规则即使面对更具体的 `allow` 规则，也照样会弹窗确认。理解这一点，才能避免"我明明写了 allow 为什么还问我"的困惑。

`deny` 规则还有两种截然不同的形态，这是新手最容易踩的坑：
- **裸工具名** `Bash`：直接把整个工具从 Claude 的上下文中移除，Claude 根本"看不见"这个工具。
- **带限定符** `Bash(rm *)`：工具仍然可用，但当 Claude 尝试执行匹配到的命令时予以拦截。

```json
{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(git commit *)",
      "Read(./.env.example)"
    ],
    "deny": [
      "Bash(git push *)",
      "Read(./.env)"
    ],
    "ask": [
      "Bash(docker *)"
    ]
  }
}
```

上面的配置含义是：放行所有 `npm run` 子命令和 `git commit`；永久拦截 `git push`；读取示例环境变量文件允许、读取真实 `.env` 拒绝；遇到 `docker` 命令每次确认。

**常见问题**：误把"想禁止的命令"写进 `deny` 的裸工具名形态（如直接写 `"Bash"`），结果整个 Bash 工具消失，Claude 连 `ls` 都不会主动用了。如果你只想拦某类命令，务必用 `Bash(命令 *)` 的带限定符形态。

## 第四步：吃透 Bash 通配符的细节陷阱

Bash 规则支持 `*` 通配符，可出现在命令的任意位置，但有两处细节决定规则是否生效：

**陷阱一：`*` 前的空格决定词边界。**
- `Bash(ls *)`（带空格）：只匹配 `ls -la`，**不匹配** `lsof`。因为空格强制要求前缀后必须跟空格或字符串结尾。
- `Bash(ls*)`（无空格）：同时匹配 `ls -la` 和 `lsof`，因为缺少词边界约束。

**陷阱二：尾通配符的两种等价写法。**
- `Bash(ls *)` 与 `Bash(ls:*)` 等价，都匹配以 `ls ` 开头的命令。
- 但 `:*` 只在**结尾**被识别为通配。若写成 `Bash(git:* push)`，冒号会被当成字面字符，无法匹配 `git` 命令——这是新手常犯的拼写错误。

**陷阱三：复合命令必须逐段匹配。**

Claude Code 能识别 shell 分隔符 `&&`、`||`、`;`、`|`、`|&`、`&` 以及换行。一条 `Bash(safe-cmd *)` 规则**不会**授权 `safe-cmd && rm -rf` 这种复合命令——系统会要求复合命令的**每一段**都独立命中规则。当你对复合命令点击"Yes, don't ask again"时，Claude Code 会为每段需要授权的子命令分别保存一条规则，单条复合命令最多保存 5 条。

**陷阱四：进程包装器的剥离是有限的。**

匹配 Bash 规则前，Claude Code 会先剥离一批固定的进程包装器：`timeout`、`time`、`nice`、`nohup`、`stdbuf`，以及不带参数的 `xargs`。所以 `Bash(npm test *)` 也能匹配 `timeout 30 npm test`。但这套剥离列表**不可配置**，且 `direnv exec`、`devbox run`、`mise exec`、`npx`、`docker exec` 等环境运行器**不在列表内**。`Bash(devbox run *)` 会匹配 `devbox run rm -rf`，因此对环境运行器必须写成精确到内部命令的规则，如 `Bash(devbox run npm test)`。同理，`watch`、`setsid`、`find -exec` 等执行型包装器**永远弹窗**，无法被前缀规则放行。

**常见问题**：试图用 `Bash(curl http://github.com/ *)` 限制 curl 只访问 GitHub，这种做法**极其脆弱**——`curl -X GET`、`https://` 协议、重定向、变量展开、多余空格等任意一种变体都能绕过。正确做法是组合三招：用 `deny` 屏蔽 `curl`/`wget`，改用 `WebFetch` 工具并配 `WebFetch(domain:github.com)`，再用 `PreToolUse` Hook 校验 URL。

## 第五步：选对权限模式（defaultMode）

权限模式决定了工具调用"默认怎么批"，在 `settings.json` 里通过 `defaultMode` 字段设置。六种模式一览：

| 模式 | 行为 | 适用场景 |
| --- | --- | --- |
| `default` | 首次使用某工具时弹窗 | 日常交互开发 |
| `acceptEdits` | 自动接受文件编辑与常见文件系统命令（`mkdir`/`touch`/`mv`/`cp`） | 大量连续改文件时 |
| `plan` | 计划模式：只读探索，不改源码 | 调研、生成方案 |
| `auto` | 自动批准，并做背景安全校验（研究预览） | 受信任的快速迭代 |
| `dontAsk` | 除已预批准的工具外，全部自动拒绝 | CI 中只允许白名单操作 |
| `bypassPermissions` | 跳过所有权限提示（高危） | 容器 / VM 等隔离环境 |

```json
{
  "defaultMode": "acceptEdits"
}
```

**安全闸门**：`bypassPermissions` 和 `auto` 模式风险较高。组织管理员可在 Managed 作用域里把 `permissions.disableBypassPermissionsMode` 或 `permissions.disableAutoMode` 设为 `"disable"`，从根上禁掉这两种模式，且不可被下级作用域覆盖。

此外，即便是 `bypassPermissions`，也有两道"硬熔断"不可关闭：
1. 显式 `ask` 规则仍会强制弹窗。
2. 针对**文件系统根目录或家目录的删除**（如 `rm -rf /`、`rm -rf ~`）始终弹窗，作为对抗模型错误的最后一道防线。

`bypassPermissions` 还会跳过对 `.git`、`.config/git`、`.claude`、`.vscode`、`.idea`、`.husky`、`.cargo`、`.devcontainer`、`.yarn`、`.mvn` 等敏感目录写入的提示——务必仅在隔离环境使用。

**常见问题**：在 CI 流水线里，最推荐的是 `dontAsk` 模式 + 一份精简的 `allow` 白名单。这样任何未列入白名单的工具调用都会被自动拒绝，既不卡流水线，又不会因意外操作破坏环境。

## 第六步：用 `/permissions` 与 `/config` 实时管理

交互式 REPL 提供了两个核心管理命令：
- `/permissions`：列出当前所有权限规则，并标注来源 `settings.json`。在这里可以直接新增、删除规则，所见即所得。
- `/config`：打开分页式设置面板，查看状态信息、修改配置项、切换权限模式。

**操作说明**：在 REPL 中输入 `/permissions`，观察刚才手写的规则是否被正确加载；再输入 `/config`，在 "Permissions" 分页里把 `defaultMode` 切到 `plan`，然后让 Claude 尝试修改一个文件，验证它是否被拒绝。

**预期结果**：`/permissions` 列出的规则与 `settings.json` 完全一致；切换到 `plan` 模式后，写操作被礼貌拒绝，Claude 转而只给出方案。

**常见问题**：有时 `/permissions` 里看到的规则比预期多——这是因为你对复合命令选过 "Yes, don't ask again"，系统为每段子命令分别存了规则。可用 `/permissions` 的删除功能清理冗余条目。

## 第七步：理解 `additionalDirectories` 与沙箱

默认情况下，Claude Code 只能读写"当前工作目录"。如果项目依赖仓库外的共享代码或资源目录，需要在 `settings.json` 里用 `additionalDirectories` 显式授予访问权：

```json
{
  "additionalDirectories": [
    "/home/user/shared-libs",
    "/home/user/docs"
  ]
}
```

**关键概念**：`additionalDirectories` 授予的是**文件访问权**，而非配置作用域——它只决定"哪些路径可被读写"，不改变任何权限规则或模式。

在 macOS 上，Claude Code 还支持沙箱（Sandbox）环境，把 Bash 命令限制在受控边界内执行，与权限规则配合形成纵深防御。沙箱路径前缀等设置可在 `settings.json` 的 `sandbox` 段配置。

**常见问题**：有人把仓库外目录加进 `additionalDirectories` 后，发现仍无法执行其中的脚本。原因是文件访问权只是第一步，执行 Bash 命令仍受 `Bash` 权限规则约束，需要同时配 `allow` 规则。

## 第八步：建立安全实践清单

把上述知识落地为四条铁律：

1. **兜底拒绝高危命令**：`deny` 列表至少包含 `Bash(rm -rf *)`、`Bash(git push *)`、`Bash(git push -f *)`、`Bash(sudo *)`。
2. **保护敏感文件**：`deny` 掉 `Read(./.env)`、`Read(./.env.*)`、`Read(./**/secrets/**)`，防止密钥进入上下文。
3. **收口网络出口**：`deny` 掉 `Bash(curl *)`、`Bash(wget *)`，改用 `WebFetch(domain:...)` 做域名级放行。
4. **隔离环境才放行**：`bypassPermissions` 仅在容器/VM 内使用，本机开发永远留在 `default` 或 `acceptEdits`。

## 实战案例：为 Node.js 团队项目配置安全基线

下面是一份可直接提交到团队仓库的 `.claude/settings.json`，综合运用本教程全部要点。场景：一个使用 npm + git + Docker 的 Node.js 服务，团队希望把开发弹窗降到最低，同时锁死危险操作。

```json
{
  "defaultMode": "acceptEdits",
  "additionalDirectories": [
    "../shared-types"
  ],
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(npm test*)",
      "Bash(npm install)",
      "Bash(npx prettier *)",
      "Bash(npx eslint *)",
      "Bash(git status)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(* --version)",
      "Bash(* --help)",
      "Read(./.env.example)",
      "WebFetch(domain:github.com)"
    ],
    "ask": [
      "Bash(docker *)",
      "Bash(npm publish)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(rm -rf /*)",
      "Bash(git push *)",
      "Bash(git push -f *)",
      "Bash(sudo *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "mcp__*"
    ]
  }
}
```

这份配置的设计逻辑：
- `defaultMode: acceptEdits` 让连续改文件不被打断，提升开发流畅度。
- `allow` 覆盖日常高频命令（构建、测试、lint、只读 git），并放行 `--version`/`--help` 这类无害查询。
- `ask` 对 `docker`、`npm publish` 这类"影响面大但偶尔需要"的命令保留人工确认。
- `deny` 兜底所有高危项：递归删除、强制推送、提权、裸网络请求、密钥文件；最后用 `mcp__*` 一刀切拒绝所有 MCP 工具的默认访问（需要时再逐个 `allow`）。

**验证步骤**：
1. 把文件存为 `<repo>/.claude/settings.json` 并提交。
2. 启动 Claude Code，运行 `/permissions` 确认规则已加载。
3. 让 Claude 执行 `npm run build`——应零弹窗通过。
4. 让 Claude 尝试 `git push`——应被直接拒绝。
5. 让 Claude 尝试读取 `.env`——应被拒绝。
6. 让 Claude 执行 `docker ps`——应弹出确认框。

若每步行为符合预期，说明安全基线已生效。

## 整体工作流程

下图展示了一次工具调用从发起到落地，Claude Code 权限系统的完整判定流程：

```mermaid
flowchart TD
    A[Claude 发起工具调用] --> B{是否只读命令<br/>内置白名单?}
    B -- 是 --> Z[直接执行 零弹窗]
    B -- 否 --> C[剥离进程包装器<br/>timeout/time/nice...]
    C --> D{deny 规则命中?<br/>裸名移除工具 / 带名拦命令}
    D -- 是 --> Y[拒绝执行]
    D -- 否 --> E{ask 规则命中?}
    E -- 是 --> F[弹窗人工确认]
    E -- 否 --> G{allow 规则命中?}
    G -- 是 --> Z
    G -- 否 --> H{defaultMode?}
    H -- default/acceptEdits --> F
    H -- plan --> P[计划模式 拒绝写操作]
    H -- dontAsk --> Y
    H -- bypassPermissions --> S{硬熔断?<br/>rm -rf / 或 rm -rf ~}
    S -- 是 --> F
    S -- 否 --> Z
    F -->|批准并记忆| Z
    F -->|拒绝| Y
```

读懂这张图，就掌握了 Claude Code 权限判定的全部逻辑分支：从只读白名单、包装器剥离，到 deny→ask→allow 的固定顺序，再到 defaultMode 兜底与硬熔断保护。

## 延伸阅读

- **PreToolUse Hooks**：当静态规则不够用时，用 Hook 在工具执行前做动态校验（如检查 URL、参数白名单），是规则系统的进阶补强。
- **Managed Settings 部署**：在 macOS（`com.anthropic.claudecode` 配置描述文件）和 Windows（`HKLM\SOFTWARE\Policies\ClaudeCode` 注册表）上做企业级集中管控。
- **Bash Sandbox**：macOS 沙箱把命令限制在受控边界，与权限规则配合形成纵深防御。
- **Subagent 权限继承**：子 Agent 默认继承主会话的权限规则，但也支持独立配置，适合给"只读调研 Agent"收紧权限。

## 训练营适用性评估

- **适合类型**：Claude Code 入门营、企业 AI 编程安全营、团队工程规范营。
- **教学时长**：建议 90 分钟（30 分钟讲解 + 45 分钟动手配置实战案例 + 15 分钟答疑）。
- **难度等级**：入门偏中阶，要求学员已能独立启动 Claude Code。
- **前置衔接**：本教程排在"安装与首个项目"之后、"Hooks 与自动化"之前，承上启下。

## 参考来源

1. [Configure permissions — Claude Code 官方文档](https://code.claude.com/docs/en/permissions) — 权限系统、规则语法、权限模式与 Bash 通配符的权威说明。
2. [Claude Code settings — Claude Code 官方文档](https://code.claude.com/docs/en/settings) — 四层作用域、settings.json 结构与配置合并优先级。
3. [Claude Code Permissions (2026): Allow Lists, Deny Rules, and Sandboxing — Claude Directory](https://www.claudedirectory.org/blog/claude-code-permissions-guide) — 四种权限模式与减少审批弹窗的实战模式总结。
4. [Claude Code settings.json Permissions — Vincent Qiao](https://blog.vincentqiao.com/en/posts/claude-code-settings-permissions/) — allow/deny/ask 配置与逐工具细粒度控制示例。
5. [Complete Guide to Claude Code Permissions — Claude Code Lab](https://claudecode-lab.com/en/blog/claude-code-permissions-guide/) — managed settings、PreToolUse Hooks 与安全配置的完整指南。

---

> 本文由「51学通信」原创整理，站长爱卫生（微信：gprshome201101）。关注获取更多 AI 编程工具与工程化实战教程。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
