首页 › tutorials › 权限系统与配置入门实战

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

概述

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

前置条件

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

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 尝试执行匹配到的命令时予以拦截。

{
  "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 等隔离环境
{
  "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 显式授予访问权:

{
  "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 服务,团队希望把开发弹窗降到最低,同时锁死危险操作。

{
  "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 权限系统的完整判定流程:

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 兜底与硬熔断保护。

延伸阅读

训练营适用性评估

参考来源

  1. Configure permissions — Claude Code 官方文档 — 权限系统、规则语法、权限模式与 Bash 通配符的权威说明。
  2. Claude Code settings — Claude Code 官方文档 — 四层作用域、settings.json 结构与配置合并优先级。
  3. Claude Code Permissions (2026): Allow Lists, Deny Rules, and Sandboxing — Claude Directory — 四种权限模式与减少审批弹窗的实战模式总结。
  4. Claude Code settings.json Permissions — Vincent Qiao — allow/deny/ask 配置与逐工具细粒度控制示例。
  5. Complete Guide to Claude Code Permissions — Claude Code Lab — 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学通信知识星球海报-扫码加入