Skip to content

05.5 权限模型与安全边界

Claude Code 敢跑你的命令,是因为有一套权限系统兜底。理解它,你才能安全地放开自动化。

读完你能做什么:为不同信任级别的场景配置合适的权限,既不被每步打断,也不担心它闯祸。


一、权限模式:一个连续谱

Claude Code 有多个权限模式,从最谨慎到最放开:

模式行为适用
plan只读探索,不能改任何东西陌生代码库、方案设计
default(别名 manual标准权限检查,逐个提示日常,需要审阅每步
acceptEdits自动接受文件编辑和常见文件系统命令你信任它改文件,但危险命令仍问
auto后台分类器审查命令和受保护目录写入平衡自动化与安全
dontAsk自动拒绝权限提示(已明确允许的仍可用)严格限制在允许清单内
bypassPermissions跳过所有权限提示⚠️ 仅隔离环境

1.1 切换方式

bash
# 启动时指定
claude --permission-mode plan
claude --permission-mode acceptEdits
text
# 会话中按 Shift+Tab 循环切换
# 或者用命令
> /plan

1.2 一个实用的渐进策略

text
新项目/陌生代码  →  plan(先看清楚)
                    ↓ 理解了
日常开发         →  default 或 acceptEdits
                    ↓ 配好了 allow 规则
成熟的自动化流程  →  auto + 精确的 allow/deny
                    ↓ 完全隔离的环境(容器/worktree)
批量无人值守     →  bypassPermissions(谨慎!)

二、权限规则语法

.claude/settings.json 中用 allow / ask / deny 三类规则精确控制。

2.1 基本结构

json
{
  "permissions": {
    "allow": [
      "Bash(npm test)",
      "Bash(npm run *)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Read",
      "Edit"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Read(./.env)",
      "Read(./secrets/**)"
    ]
  }
}

2.2 规则匹配

写法含义
Read允许/拒绝整个工具
Bash(npm test)只匹配精确命令
Bash(git diff *)* 是通配,匹配 git diff 开头
Read(./secrets/**)路径通配,匹配 secrets 目录下所有
mcp__*匹配所有 MCP 工具
mcp__github__*匹配 github server 的所有工具

2.3 三类规则的优先级

text
deny  >  ask  >  allow

deny 永远赢。即使某命令在 allow 里,只要 deny 也匹配,就被拒绝。用这个特性设护栏

json
{
  "permissions": {
    "allow": ["Bash(git *)"],
    "deny": ["Bash(git push --force *)", "Bash(git reset --hard *)"]
  }
}

"允许所有 git 命令,但 force push 和 hard reset 除外。"


三、必配的安全护栏

无论你多信任它,这几条 deny 规则建议长期开着:

json
{
  "permissions": {
    "deny": [
      "Bash(rm -rf /*)",
      "Bash(rm -rf ~)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./**/*secret*)",
      "Read(./**/id_rsa)",
      "Read(./**/credentials*)",
      "Bash(git push --force*)",
      "Bash(curl * | bash)",
      "Bash(curl * | sh)"
    ]
  }
}

理由:

  • 防误删 —— rm -rf
  • 防密钥泄露到上下文 —— 读到 .env 就进上下文了,可能被后续输出带出去
  • 防危险的远程执行 —— curl | bash 是供应链攻击的经典入口
  • 防历史破坏 —— force push

四、Additional Directories

默认情况下,Claude Code 只能读写你启动它的目录(及其子目录)。

bash
# 临时增加可访问目录
claude --add-dir ../shared-lib ../config
json
// 持久化
{
  "permissions": {
    "additionalDirectories": ["../shared-lib"]
  }
}

注意--add-dir 授予的是文件访问权,但这些目录里的 .claude/ 配置默认不会被加载(除非设 CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1)。


五、沙箱模式

在支持的平台上,可以让 Claude Code 在沙箱里运行,进一步隔离:

text
> /sandbox
json
{
  "sandbox": {
    "enabled": true
  }
}

沙箱提供 OS 级的隔离,即使权限规则有疏漏,破坏范围也被限制。这是无人值守自动化的推荐配置。


六、--dangerously-skip-permissions 的正确用法

这个 flag 跳过所有权限提示。它有合法用途,但必须配合隔离。

6.1 什么时候可以用

text
✅ 在 Docker 容器里,代码是一次性的
✅ 在 CI 的隔离 runner 里
✅ 在 git worktree + 沙箱里做实验

6.2 什么时候绝对不要用

text
❌ 在你的主开发机上,对着重要仓库
❌ 有生产凭据的环境
❌ 能访问你个人文件的目录

6.3 更安全的替代

与其完全跳过,不如用精确的 allow 清单达到"该自动的自动,该拦的拦":

bash
claude \
  --allowedTools "Bash(npm *)" "Bash(git add *)" "Bash(git commit *)" "Read" "Edit" "Write" \
  --disallowedTools "Bash(rm *)" "Bash(git push *)" "mcp__*"

这比 bypassPermissions 安全得多,又能免去大部分打断。

6.4 与 daemon 子命令的交互(v2.1.199+)

bash
# 从 v2.1.199 起,前导的 --dangerously-skip-permissions 会正确路由到 daemon 子命令
claude --dangerously-skip-permissions daemon status

七、提示词 vs 权限:一条重要界线

权限系统是确定性的,提示词是概率性的。

text
你想禁止某个操作
├─ 用提示词说"不要 rm -rf"     →  概率性,可能失效
└─ 用 deny 规则 Bash(rm -rf *)  →  确定性,永远生效

任何"必须保证"的边界,都应该用权限规则或 hook 实现,而不是写在 CLAUDE.md 里祈祷它遵守。这条界线在本手册反复出现,因为它是安全使用 Agent 的核心。详见 04.2 元技巧 206.5 Hooks


八、Auto Mode 的分类器

auto 模式用一个后台分类器判断命令的风险。你可以查看它的规则:

bash
claude auto-mode defaults              # 打印内置分类规则(JSON)
claude auto-mode config                # 查看应用了你的设置后的有效配置
claude auto-mode defaults --label 'Git Destructive'   # 只看某类规则

重置为默认:

bash
claude auto-mode reset --yes           # v2.1.212+

这让你能理解"为什么某个命令被自动允许/拦截",而不是黑盒。


九、企业管控

组织可以下发不可被个人覆盖的策略。相关内容见 10.3 企业级管控

  • permissions.deny 在 managed settings 里,个人无法解除
  • allowManagedHooksOnly 只允许管理员批准的 hook
  • forceLoginMethod / forceLoginOrgUUID 锁定认证

十、配置模板:三种信任级别

10.1 谨慎级(陌生代码/重要仓库)

json
{
  "permissions": {
    "defaultMode": "plan",
    "deny": [
      "Bash(rm -rf *)", "Read(./.env*)", "Read(./**/*secret*)",
      "Bash(git push*)", "Bash(curl * | *sh)"
    ]
  }
}

10.2 平衡级(日常开发)

json
{
  "permissions": {
    "defaultMode": "acceptEdits",
    "allow": [
      "Bash(npm *)", "Bash(git status)", "Bash(git diff *)",
      "Bash(git add *)", "Bash(git commit *)", "Read", "Edit", "Write"
    ],
    "ask": ["Bash(git push *)"],
    "deny": [
      "Bash(rm -rf *)", "Read(./.env*)", "Bash(git push --force*)"
    ]
  }
}

10.3 自动化级(隔离环境 + 精确清单)

json
{
  "sandbox": { "enabled": true },
  "permissions": {
    "defaultMode": "auto",
    "allow": [
      "Bash(npm *)", "Bash(git *)", "Read", "Edit", "Write", "Glob", "Grep"
    ],
    "deny": [
      "Bash(rm -rf /*)", "Bash(git push --force*)",
      "Read(./.env*)", "mcp__*(*delete*)"
    ]
  }
}

延伸阅读

基于 VitePress 构建 · 内容采用原作者授权