claude-code/docs/agentic-design/04-permission-system.md
Claude 808d5a61b3
docs: Add comprehensive agentic design documentation (2.5-hour learning session)
新增 docs/agentic-design/ 教育文档,全中文+英文技术术语,覆盖:

- README.md: 总索引,整体架构图,阅读指南
- 00-codebase-tour.md: 代码库全景,递归覆盖所有重要目录
- 01-agent-loop.md: Query loop 状态机,token budget,compaction
- 02-tool-system.md: Tool interface,权限检查,并发执行,sibling abort
- 03-multi-agent-coordination.md: Agent 类型,coordinator 4 阶段,XML 通信
- 04-permission-system.md: Permission mode,rule system,YOLO 分类器,denial tracking
- 05-context-and-memory.md: System prompt 分层,compaction,auto-dream 后台巩固
- 06-feature-gating.md: Compile-time feature,runtime flags,Bun dead-code elimination

总计 ~2.5 小时阅读,每篇含 Design Decision 专栏和常见误解纠正

https://claude.ai/code/session_017Vdqo9B8eTXiEDcqnv9DxM
2026-03-31 16:07:29 +00:00

8.7 KiB
Raw Blame History

Permission 系统Agent 的沙箱

为什么需要权限管控?

想象 Claude 可以执行任意 bash 命令。用户说"帮我看看网站"Claude 可能:

  • 合法地执行 curl https://example.com
  • 也可能执行 rm -rf / ← 灾难

权限系统的目标

  1. 阻止意外的危险操作
  2. 提示用户"你确定吗?"
  3. 在保留便利的同时维护安全

Claude Code 的 permission 系统是一个多层防线


核心概念Permission Mode

系统支持多种权限模式,用户可以选择:

Mode 特点 场景
default 每次都问用户 不信任 agent想完全控制
auto ML 分类器自动审批 信任 agent想要流畅体验
acceptEdits 自动接受文件编辑(但仍然问危险操作) 开发工作流(改代码 OK执行脚本要问
bypass 完全自动,不问(谨慎使用) 内部测试、自动化流程
dontAsk (aka yolo) 拒绝所有非低风险操作 沙箱环境,最安全
plan 特殊模式:进入计划编辑阶段 用户审核计划后再执行

用户在启动时选择(环境变量或配置文件):

# 每次都问
claude-code --permission-mode default

# 自动审批
claude-code --permission-mode auto

# 最安全
claude-code --permission-mode dontAsk

相关文件:utils/permissions/PermissionMode.ts


Permission 决策 Pipeline

当 agent 试图执行一个 tool 时,系统会问:"我应该允许吗?"

Agent 调用: BashTool { command: "npm test" }
  │
  ├─ [1] Mode 检查
  │      if mode == "bypass" → ✓ 允许,返回
  │      if mode == "dontAsk" → ✗ 拒绝 Bash返回
  │
  ├─ [2] 规则匹配
  │      检查用户配置的规则列表
  │      如: "Bash(git *)" → 允许 git 命令
  │         "Bash(npm *)" → 允许 npm 命令
  │         "Bash(*)" → 允许任意 bash (太宽)
  │
  │      我们的命令 "npm test" 匹配 "npm *" → ✓
  │
  ├─ [3] 风险分类
  │      rule match → LOW 风险
  │      如果没匹配到规则,分类器决定风险等级
  │
  ├─ [4] YOLO 分类器
  │      对于 MEDIUM 风险的操作:
  │      - 如果被模型认为"明显安全",自动批准
  │      - 否则需要用户确认
  │
  └─ [5] 最后手段:提示用户
         用户选择: ✓ 允许 / ✗ 拒绝 / ⚠️ 改规则

相关文件:utils/permissions/permissions.ts (52 KB核心决策逻辑)


规则系统

用户可以配置规则,告诉 agent 什么是自动允许的。规则语法:

Bash(git *)        # 允许任何 git 命令
Bash(npm install)  # 只允许 npm install不允许 npm test
FileEdit(src/*.ts) # 允许编辑 src/ 下的 .ts 文件
FileRead(/*)       # 允许读任何文件

规则支持 glob 模式* 通配符)。

规则分层

规则可以来自多个地方(优先级从高到低):

  1. CLI 参数--approve-file "FileEdit(src/*.ts)"
  2. 项目配置.claude/settings.json 中的 approvals
  3. 用户设置~/.claude/settings.json
  4. 系统默认Claude Code 内置的基础规则

下层规则会被上层规则覆盖。

相关文件:utils/permissions/permissionRuleParser.ts, utils/permissions/permissionsLoader.ts


YOLO 分类器ML 自动审批

对于规则未覆盖的操作system 用 YOLO 分类器("You Only Live Once")决定:

输入:
  tool_name: "BashTool"
  command: "npm test"
  context: 当前任务是"修复 bug"

分类器说: "这个操作很像是开发者会做的正常事,批准"

结论: 自动允许,不问用户

分类器基于 ML 训练,考虑:

  • Tool 类型BashTool 比 FileReadTool 高风险)
  • 具体命令(npm testrm -rf 安全)
  • 当前上下文("修复 bug" vs "浏览网页"

相关文件:utils/permissions/yoloClassifier.ts (52 KB)

分类器的风险等级

LOW
  → 自动允许(不问用户)
  → 例FileReadTool, GlobTool, WebFetchTool

MEDIUM
  → 取决于 modeauto mode 用分类器default mode 问用户)
  → 例FileEditTool, BashTool (git 命令)

HIGH
  → 一般不自动允许(需要用户确认)
  → 例BashTool (rm -rf), FileWriteTool (覆盖重要文件)

Denial TrackingCircuit Breaker

如果用户连续拒绝 agent 多次system 会自动降级权限模式

用户拒绝:
  1. "BashTool"  ← Denial #1
  2. "FileEditTool" ← Denial #2
  3. "BashTool" ← Denial #3

连续 3 次拒绝触发!
  ↓
系统切换到 "default" mode后续所有操作都要问用户

这样防止:
- Agent 持续尝试被拒的操作
- 用户一直看到提示烦不胜烦

同时,系统还追踪总拒绝数

同一 session 中总共拒绝了 20 次
  ↓
系统记录日志:"这个 session 决策质量差,建议用户审视任务"

相关文件:utils/permissions/denialTracking.ts


路径安全:防止路径遍历攻击

即使规则写得再好,攻击者也可能用特殊编码绕过:

规则: FileEdit(src/*.ts)  ← 只允许 src/ 目录

攻击尝试:
  path: "src/../../../etc/passwd"  ← 试图逃逸
  path: "src%2f..%2f..%2fetc%2fpasswd" ← URL 编码
  path: "src/\u202e../../../etc/passwd" ← Unicode 隐藏字符

系统有多层防御:

  1. Path Normalization

    "src/../../../etc/passwd"
      → 规范化
    → "/etc/passwd"
      → 检查是否在 src/ 内? 否 → 拒绝
    
  2. URL Decoding

    "src%2f..%2f..%2fetc"
      → 解码
    → "src/../../etc"
      → 规范化 → 拒绝
    
  3. Unicode Normalization

    Unicode 隐藏字符也会被清理
    

相关文件:utils/permissions/pathValidation.ts (62 KB)


Protected Files黑名单

某些文件永远不会被自动编辑

.gitconfig          ← Git 配置,修改可能破坏工作流
.bashrc, .zshrc     ← Shell 配置,修改可能卡住终端
.mcp.json           ← MCP 配置,影响工具可用性
.claude.json        ← Claude Code 自己的配置

这些文件即使通过了权限检查,也会再次提示用户确认。


Design Decision 专栏

为什么需要 ML 分类器?

如果只用规则:

允许所有 Bash 命令?
  → 太宽,不安全(用户可能 rm -rf

只允许 git/npm 命令?
  → 太窄不便利sudo docker pull 被拒)

ML 分类器的优势:

可以说"这个命令看起来是在开发工作流的一部分,
而不是破坏性操作,所以允许"

如果出错classify 有假阴性),系统还有:
  - Denial tracking连续拒绝降级
  - Protected files黑名单
  - Circuit breaker

所以 ML 不是唯一防线,而是多层防御中的一层

为什么规则支持 Glob 而不是正则表达式?

Globsrc/*.ts → 简单直观 正则:^src/[^/]+\.ts$ → 复杂,容易写错

目标用户是工程师,但不是安全专家。Glob 的错误率更低。


常见误解

误解 1"Permission mode 是全局的,改一次就生效?"

实际:可以在 CLI 参数中针对单个命令覆盖:

claude-code --permission-mode auto /commit  # 这个 /commit 用 auto mode
claude-code --permission-mode default /config # 这个 /config 用 default mode

误解 2"YOLO 分类器是完美的?"

实际:分类器是 best-effort,有假阳性和假阴性。假阴性(该拒的通过了)会被 denial tracking 捕捉到。

误解 3"Protected files 名单是硬编码的?"

实际:可以通过配置扩展:

{
  "protectedFiles": [".gitconfig", ".bashrc", ".my-precious-file"]
}

关键要点

  1. Permission modedefault(每次问), autoML 自动), acceptEdits, bypass, dontAsk
  2. 决策 pipelineMode → Rules → Risk Classification → YOLO → User Prompt
  3. 规则系统Glob 模式分层来源CLI > project > user > default
  4. YOLO 分类器ML 自动批准 MEDIUM 风险操作,不需要用户每次确认
  5. Denial tracking:连续 3 次拒绝自动降级权限,防止烦人的重复提示
  6. 路径安全多层防御normalization, URL decode, Unicode clean
  7. Protected files:黑名单,永远要再次确认

深入阅读

  • utils/permissions/permissions.ts:完整决策逻辑
  • utils/permissions/yoloClassifier.ts:分类器实现
  • utils/permissions/pathValidation.ts:路径安全
  • utils/permissions/denialTracking.tsDenial tracking
  • utils/permissions/PermissionMode.tsMode 定义

下一步:了解Context 和 Memory 系统,看看当 context window 快满时会发生什么。