乐于分享
好东西不私藏

Claude Code源码分析之 权限系统

Claude Code源码分析之 权限系统

权限系统

本章概要

权限系统是 Claude Code 安全的核心。它确保 AI 的操作经过适当的授权,防止意外或恶意的系统修改。本章深入剖析三层权限决策架构。

前置知识:第4章 Context 管理后续章节:第6章工具系统


5.1 三层决策架构

┌─────────────────────────────────────────────────────────────────────┐│                     Permission Decision Flow                         │├─────────────────────────────────────────────────────────────────────┤│                                                                      ││  ┌──────────┐     ┌──────────┐     ┌──────────────────────────┐    ││  │   Hook   │────▶│  Rules   │────▶│  Interactive Prompt      │    ││  │ (PreTool)│     │  deny/   │     │  (user confirmation)     │    ││  │          │     │  allow   │     │                          │    ││  └──────────┘     └──────────┘     └──────────────────────────┘    ││       │                │                      │                    ││       ▼                ▼                      ▼                    ││   ┌────────┐      ┌────────┐            ┌────────┐               ││   │  Deny   │      │ Allow  │            │  Ask   │               ││   │(blocked)│      │(executed)│           │(pending)│               ││   └────────┘      └────────┘            └────────┘               ││                                                                      │└─────────────────────────────────────────────────────────────────────┘

5.2 Hook 层

5.2.1 preToolUse 事件

Hook 在工具执行前触发:

interface PreToolUsePayload {  toolName: string;  params: Record<stringany>;  sessionId: string;  autoMode: boolean;}asyncfunctionhandlePreToolUse(  payload: PreToolUsePayload): Promise<HookResponse{// 调用外部 Hook 脚本const result = await spawnHook('pre-tool-use', payload);if (result.action === 'block') {return { allowed: false, reason: result.reason };  }if (result.action === 'modify') {return { allowed: true, modifiedParams: result.params };  }return { allowed: true };}

5.2.2 postToolUse 事件

工具执行后触发,用于审计:

asyncfunctionhandlePostToolUse(  payload: PostToolUsePayload): Promise<void{// 记录执行日志await logToolExecution(payload);// 检测异常行为if (payload.toolName === 'Bash') {await detectAnomalousCommand(payload);  }}

5.3 Rules 层

5.3.1 规则格式

// [源码位置] src/types/permissions.ts:45-62 规则匹配类型exporttype PermissionRule =   | { type'exact'; command: string; effect: 'allow' | 'deny' | 'ask' }  | { type'prefix'; prefix: string; effect: 'allow' | 'deny' | 'ask' }  | { type'wildcard'; pattern: string; effect: 'allow' | 'deny' | 'ask' }// 匹配优先级:exact > prefix > wildcard

5.3.2 三层权限决策流程图

工具调用请求    │    ▼Hook 层检查 → 返回 deny → 直接拒绝    │    ▼返回 allow/unknown → Rules 层匹配    │    ▼返回 deny → 直接拒绝返回 allow → 放行返回 unknown → Auto Mode 分类器    │    ▼Stage 1 初筛 → 白名单 → 放行    │    ▼非白名单 → Stage 2 深度分析 → ALLOW/DENY/ASK    │    ▼返回 ASK → 用户确认对话框 → 接受/拒绝

5.3.3 Bash 命令分类器工作流图

Bash 命令输入 → 精确匹配检查 → 匹配 → 应用规则    │    ▼不匹配 → 路径前缀检查 → 匹配 → 应用规则    │    ▼不匹配 → 命令名前缀检查 → 匹配 → 应用规则    │    ▼不匹配 → 通配符检查 → 匹配 → 应用规则    │    ▼不匹配 → 默认规则 → ask 用户确认

5.3.2 Bash 命令匹配

Bash 规则支持多种匹配模式:

模式
示例
说明
Exact
/usr/bin/curl
精确匹配
PathPrefix
/usr/bin/rm *
路径前缀
CommandPrefix
curl -X *
命令前缀
Wildcard
git *
通配符

5.3.3 匹配算法

// [源码位置] src/services/permission/rules.tsfunctionmatchBashRule(command: string, rule: BashRule): MatchType | null{// 1. 精确匹配if (rule.pattern === command) {return MatchType.Exact;  }// 2. 路径前缀匹配if (rule.pattern.startsWith('/') &&       command.startsWith(rule.pattern)) {return MatchType.PathPrefix;  }// 3. 命令名前缀匹配const commandName = command.split(' ')[0];if (commandName === rule.pattern ||       commandName.startsWith(rule.pattern + ' ')) {return MatchType.CommandPrefix;  }// 4. 通配符匹配if (rule.pattern.includes('*')) {const regex = globToRegex(rule.pattern);if (regex.test(command)) {return MatchType.Wildcard;    }  }returnnull;}

5.4 Interactive Prompt 层

5.4.1 用户确认对话框

当 Hook 和 Rules 都无法决策时:

┌─────────────────────────────────────────────────────────────────┐│  ⚠️  Tool Permission Required                                   │├─────────────────────────────────────────────────────────────────┤│                                                                  ││  Tool: Bash                                                      ││  Command: rm -rf /tmp/cache/*                                   ││  Risk: High - deletes files                                     ││                                                                  ││  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         ││  │    Deny      │  │   Allow      │  │ Allow and    │         ││  │              │  │   Once       │  │ Remember     │         ││  └──────────────┘  └──────────────┘  └──────────────┘         ││                                                                  │└─────────────────────────────────────────────────────────────────┘

5.4.1 决策存储

用户可以选择”记住决策”,下次同类操作自动应用:

interface StoredDecision {  pattern: string;  action: 'allow' | 'deny';  expiresAt: number;  // 过期时间}// 存储在 settings.json{"permissionDecisions": [    { "pattern""git *""action""allow""expiresAt"1712400000 }  ]}

5.5 Auto Mode 分类器

5.5.1 双层设计

Auto Mode 使用双层分类器进行无干预决策:

层级
上下文
用途
Stage 1
64 tokens
快速初筛
Stage 2
4096 tokens
深度分析

5.5.2 Stage 1:快速初筛

class Stage1Classifier {private whitelist = new Set(['git status''git log''ls''pwd''cat','head''tail''grep''find'// ... ~50 个  ]);async classify(request: ToolRequest): Promise<Classification> {const cmdHash = hashCommand(request.params.command);if (this.whitelist.has(cmdHash)) {return { decision: 'allow', confidence: 0.95 };    }return { decision: 'unknown', confidence: 0.0 };  }}

5.5.3 Stage 2:深度分析

class Stage2Classifier {async classify(request: ToolRequest): Promise<Classification> {const context = awaitthis.buildContext(request, {      maxTokens: 4096,      includeHistory: true    });const prompt = `分析此命令是否安全:命令: ${context.command}任务: ${context.currentTask}历史: ${context.recentHistory}考虑:1. 是否修改系统状态?2. 是否删除数据?3. 是否发起网络请求?回复: ALLOW | DENY | ASK    `.trim();returnthis.model.generate(prompt);  }}

5.6 权限系统配置

5.6.1 settings.json 配置

{"permissions": {"defaultLevel""ask","autoMode": {"stage1Enabled"true,"stage2Enabled"true    },"rules": [      { "tool""Bash""pattern""git *""action""allow" },      { "tool""Bash""pattern""/usr/bin/sudo *""action""ask" },      { "tool""Bash""pattern""rm -rf *""action""deny" }    ]  }}

5.7 设计模式与最佳实践

5.7.1 设计模式分析

  • 责任链模式:Hook → Rules → Auto Mode → Prompt,任意一层返回明确决策就终止流程
  • 规则引擎模式:可配置的权限规则,无需修改代码即可调整安全策略
  • 分层分类器:64 tokens 快速初筛 + 4096 tokens 深度分析,平衡性能和准确性

5.7.2 最佳实践

  • 自定义权限规则优先使用 exact 精确匹配,避免 wildcard 通配符导致的安全风险
  • 高风险命令(sudo、rm -rf 等)应该显式配置为 ask 或 deny
  • Auto Mode 仅对白名单的只读工具自动放行,修改类操作始终要求确认

5.7.3 常见问题与调试技巧

  1. 权限规则不生效

    • 调试:运行 /permissions list 查看当前规则列表
    • 定位:检查规则优先级,exact 优先级高于 wildcard
    • 解决:调整规则顺序,高风险规则放在前面
  2. Auto Mode 拒绝了允许的命令

    • 调试:运行 /permissions debug 查看分类器决策过程
    • 定位:可能不在白名单中,或者 Stage 2 分类器判断风险过高
    • 解决:添加显式 allow 规则到 settings.json

5.7.4 设计权衡

  • Auto Mode 双层分类器
    • ✅ 优点:95%的场景可以快速决策,无需用户干预
    • ❌ 缺点:存在误判风险,仅对白名单工具自动放行
    • 决策背景:平衡用户体验和安全性,高频低风险操作自动处理

修正说明:Auto Mode 不是允许所有工具调用,仅对白名单中的只读工具(Read、Grep、Glob等)自动放行,修改类工具仍需要用户确认。


5.8 小结

本章完成了以下内容:

  1. 三层决策:Hook → Rules → Interactive Prompt
  2. Hook 层:preToolUse/postToolUse 事件
  3. Rules 层:精确、前缀、通配符匹配
  4. Interactive 层:用户确认对话框
  5. Auto Mode:64 tokens 初筛 + 4096 tokens 深度分析

下一步:第6章将深入分析工具系统,这是 Claude Code 与世界交互的核心桥梁。


源码位置

  • 权限系统:src/services/permission/system.ts
  • 规则匹配:src/services/permission/rules.ts
  • 分类器:src/services/permission/classifier.ts