Claude Code Wiki
首页 深入解析 服务层

权限服务:PermissionMode 与动态权限验证

高级 服务层

Claude Code 的权限服务是整个系统安全模型的核心,负责在 AI 执行工具操作前进行细粒度的权限控制和动态验证。该服务通过 PermissionMode 模式系统多层级规则引擎智能分类器 三层架构,实现了从完全交互式到完全自动化的渐进式信任模型,在保证安全性的同时最大化操作效率。

核心架构:三层权限控制模型

Claude Code 的权限系统采用分层设计,每一层都有明确的职责边界:PermissionMode 定义整体交互策略(从交互式到自动化),Permission Rules 提供基于工具和参数的细粒度白名单/黑名单控制,Classifier 则在 Auto 模式下通过 AI 动态评估操作安全性。这种设计使得系统可以根据用户信任级别、操作风险和环境上下文灵活调整验证策略。

Sources: types/permissions.ts, Tool.ts

graph TB
    A[Tool Execution Request] --> B{PermissionMode Check}
    B -->|default| C[Interactive Permission Flow]
    B -->|acceptEdits| D[Fast-path: CWD Edits Only]
    B -->|plan| E[Plan Mode Validation]
    B -->|auto| F[AI Classifier Decision]
    B -->|bypassPermissions| G[Allow All - Admin Only]
    B -->|dontAsk| H[Auto-deny Mode]
    
    C --> I{Permission Rules}
    I -->|Allow Rule Match| J[Allow]
    I -->|Deny Rule Match| K[Deny]
    I -->|Ask Rule Match| L[Prompt User]
    I -->|No Match| L
    
    F --> M{Classifier Result}
    M -->|Allow| J
    M -->|Deny| K
    M -->|Ask| L
    
    L --> N[Permission Dialog UI]
    N --> O{User Decision}
    O -->|Allow + Remember| P[Persist Rule to Settings]
    O -->|Allow Once| J
    O -->|Deny| K
    
    J --> Q[Execute Tool]
    K --> R[Reject with Message]
    
    style F fill:#f9f,stroke:#333,stroke-width:4px
    style N fill:#bbf,stroke:#333,stroke-width:2px
    style I fill:#bfb,stroke:#333,stroke-width:2px

PermissionMode 模式体系

PermissionMode 定义了六种权限交互模式,每种模式代表不同的自动化程度和安全级别。default 模式是标准交互式验证,对所有敏感操作都提示用户;acceptEdits 模式自动允许当前工作目录下的文件编辑操作;plan 模式专为规划阶段设计,限制破坏性操作;auto 模式通过 AI 分类器动态决策(仅限 Anthropic 内部);bypassPermissions 模式完全绕过权限检查(仅限管理员);dontAsk 模式自动拒绝所有需要权限的操作,适用于后台任务。

Sources: utils/permissions/PermissionMode.ts, types/permissions.ts

模式交互级别适用场景安全性可用性
default完全交互式标准开发工作流最高所有用户
acceptEdits半自动快速文件编辑迭代中高所有用户
plan受限交互规划与设计阶段所有用户
autoAI 决策自动化工作流Anthropic 内部
bypassPermissions完全自动管理员操作/测试管理员专用
dontAsk自动拒绝后台异步任务最高(保守)系统内部

模式之间的转换通过 getNextPermissionMode 函数实现循环切换,用户可以通过 Shift+Tab 快捷键在模式间切换。模式转换时,系统会执行相应的状态转换逻辑,例如进入 auto 模式时会剥离危险权限规则,退出时恢复这些规则。

Sources: utils/permissions/getNextPermissionMode.ts, utils/permissions/permissionSetup.ts

动态权限验证流程

当工具请求执行时,权限系统按照严格的优先级顺序进行验证:钩子系统拦截模式级别检查规则匹配分类器评估用户交互。每个阶段都可以提前终止流程,返回 allow/deny/ask 决策。

验证流程的五个阶段

第一阶段:钩子系统拦截(Hook Pre-check)。权限系统首先执行用户配置的权限钩子,这些钩子可以基于自定义逻辑拒绝或允许操作。钩子通过 executePermissionRequestHooks 函数执行,如果任何钩子返回拒绝决策,整个流程立即终止。

第二阶段:模式级别快速路径(Mode Fast-path)。根据当前 PermissionMode,系统应用不同的快速路径逻辑。在 bypassPermissions 模式下,所有操作直接允许;在 dontAsk 模式下,所有需要权限的操作直接拒绝;在 acceptEdits 模式下,工作目录内的文件编辑操作自动允许。

第三阶段:规则匹配引擎(Rule Matching Engine)。系统按照优先级顺序检查权限规则:deny 规则 → allow 规则 → ask 规则。规则来源包括用户设置、项目设置、本地设置、策略设置、CLI 参数、命令和会话。每个规则包含工具名称和可选的规则内容,支持精确匹配、前缀匹配和通配符匹配。

第四阶段:分类器评估(Classifier Evaluation)。仅在 auto 模式或启用了自动分类器的 plan 模式下执行。分类器使用 AI 模型评估操作的安全性,考虑操作上下文、历史对话和用户定义的允许/拒绝规则。分类器可以返回 allow/deny/ask 决策,置信度分为高/中/低三个级别。

第五阶段:用户交互(User Interaction)。如果前面所有阶段都返回 ask 决策,系统会显示权限请求对话框,等待用户决策。用户可以选择允许一次、始终允许(持久化规则)、拒绝或提供反馈。对话框会显示操作详情、预览(对于文件编辑)和安全提示。

Sources: utils/permissions/permissions.ts, hooks/toolPermission/handlers/interactiveHandler.ts

sequenceDiagram
    participant Tool
    participant PermissionSystem
    participant Hooks
    participant Rules
    participant Classifier
    participant UserUI
    
    Tool->>PermissionSystem: checkPermissions(input, context)
    PermissionSystem->>Hooks: executePermissionRequestHooks()
    alt Hook Denies
        Hooks-->>PermissionSystem: {behavior: 'deny'}
        PermissionSystem-->>Tool: Deny Decision
    else Hook Allows or No Hooks
        Hooks-->>PermissionSystem: {behavior: 'allow'/'ask'}
        
        PermissionSystem->>PermissionSystem: Check PermissionMode
        
        alt Bypass Mode
            PermissionSystem-->>Tool: Allow Decision
        else DontAsk Mode
            PermissionSystem-->>Tool: Deny Decision
        else Auto/AcceptEdits Mode
            PermissionSystem->>PermissionSystem: Apply Fast-path Logic
        end
        
        PermissionSystem->>Rules: Match Rules (deny→allow→ask)
        
        alt Rule Match Found
            Rules-->>PermissionSystem: Rule Decision
            alt Decision is Allow/Deny
                PermissionSystem-->>Tool: Return Decision
            end
        end
        
        alt Auto Mode & No Rule Match
            PermissionSystem->>Classifier: classifyYoloAction()
            Classifier->>Classifier: AI Safety Evaluation
            Classifier-->>PermissionSystem: Classifier Result
            
            alt Classifier Allows/Denies
                PermissionSystem-->>Tool: Return Decision
            end
        end
        
        PermissionSystem->>UserUI: Show Permission Dialog
        UserUI->>UserUI: User Reviews & Decides
        UserUI-->>PermissionSystem: User Decision + Updates
        PermissionSystem->>PermissionSystem: Persist Updates if Needed
        PermissionSystem-->>Tool: Final Decision
    end

PermissionDecision 决策类型

权限验证的结果是 PermissionDecision 对象,包含三种行为类型:allow(允许执行)、ask(需要用户确认)、deny(拒绝执行)。每种决策都携带丰富的元数据,用于解释决策原因、提供用户反馈和记录审计日志。

PermissionAllowDecision 包含 updatedInput(工具可以修改输入参数,例如规范化路径)、userModified(标记用户是否手动修改了输入)、decisionReason(决策原因,例如匹配的规则或模式)、contentBlocks(可选的内容块,例如用户粘贴的图片反馈)。

PermissionAskDecision 包含 message(显示给用户的提示消息)、suggestions(建议的权限更新,例如”始终允许此操作”)、pendingClassifierCheck(对于 Bash 工具,可以在后台运行分类器检查)、blockedPath(如果操作被路径限制阻止,显示阻止的路径)。

PermissionDenyDecision 包含 message(拒绝原因)、decisionReason(详细的拒绝原因,用于日志和调试)、toolUseID(关联的工具使用 ID)。

Sources: types/permissions.ts, utils/permissions/PermissionResult.ts

权限规则系统

权限规则是细粒度访问控制的核心,每个规则定义了工具名称、可选的规则内容和行为。规则通过多个来源加载,按照优先级合并,支持精确匹配、前缀匹配和通配符模式。

规则来源与优先级

权限规则从六个来源加载,优先级从高到低:CLI 参数 > 命令 > 会话 > 用户设置 > 项目设置 > 本地设置 > 策略设置。CLI 参数和命令规则具有最高优先级,用于临时覆盖;会话规则在当前会话期间有效;用户设置和项目设置提供持久化配置;策略设置由组织管理员控制,可以强制执行安全策略。

permissionsLoader.ts 中的 loadAllPermissionRulesFromDisk 函数负责从所有来源加载规则。如果启用了 allowManagedPermissionRulesOnly 策略设置,系统只加载策略规则,忽略所有其他来源,这为组织提供了集中控制权限的能力。

Sources: utils/permissions/permissionsLoader.ts, utils/permissions/PermissionRule.ts

规则匹配算法

规则匹配支持三种模式:工具级别匹配(例如 Bash 匹配所有 Bash 命令)、前缀匹配(例如 Bash(git:*) 匹配所有以 git 开头的命令)、精确内容匹配(例如 Bash(npm test) 只匹配 npm test 命令)。对于 MCP 工具,规则支持服务器级别匹配(mcp__server1 匹配服务器的所有工具)和通配符(mcp__server1__*)。

规则匹配函数 toolMatchesRule 首先检查规则是否有内容,如果没有内容且工具名称完全匹配,则匹配成功。对于 MCP 工具,函数解析工具名称中的服务器和工具部分,支持服务器级别规则匹配。shellRuleMatching.ts 提供了针对 Shell 命令的专门匹配逻辑,处理复合命令、管道和重定向。

Sources: utils/permissions/permissions.ts, utils/permissions/shellRuleMatching.ts

规则持久化与更新

当用户在权限对话框中选择”始终允许”或”始终拒绝”时,系统创建 PermissionUpdate 对象并持久化到相应的设置源。PermissionUpdate 支持五种操作类型:addRules(添加规则)、replaceRules(替换规则)、removeRules(移除规则)、setMode(设置模式)、addDirectories/removeDirectories(管理额外工作目录)。

applyPermissionUpdate 函数将更新应用到 ToolPermissionContext,更新相应的规则集合。persistPermissionUpdates 函数将更新写入磁盘上的设置文件,支持用户设置、项目设置和本地设置。更新立即生效,无需重启会话。

Sources: utils/permissions/PermissionUpdate.ts, types/permissions.ts

智能分类器:Auto 模式的核心

Auto 模式通过 AI 分类器实现智能权限决策,在保证安全的前提下最大化自动化程度。分类器分析操作上下文、用户定义的规则和历史对话,动态评估操作的安全性。

分类器架构与工作流程

分类器系统由三个核心组件构成:YOLO 分类器(主分类器,使用 AI 模型评估操作)、Bash 分类器(针对 Bash 命令的专门分类器,支持基于描述的规则)、拒绝跟踪器(Denial Tracker,跟踪连续拒绝次数,防止分类器陷入拒绝循环)。

当 auto 模式激活时,系统首先检查工具是否在安全白名单中(例如只读工具如 FileReadToolGrepTool),白名单工具直接允许。对于需要评估的工具,系统尝试 acceptEdits 快速路径:如果操作在 acceptEdits 模式下会被允许(例如工作目录内的文件编辑),则直接允许,避免昂贵的分类器 API 调用。

如果快速路径不适用,系统调用 classifyYoloAction 函数,构建分类器提示词,包括用户定义的允许/拒绝规则、环境描述和历史对话上下文。分类器使用 AI 模型评估操作,返回 allow/deny/ask 决策和置信度。高置信度的 allow/deny 决策直接应用,低置信度或 ask 决策回退到用户交互。

Sources: utils/permissions/yoloClassifier.ts, utils/permissions/classifierDecision.ts, utils/permissions/denialTracking.ts

分类器提示词构建

分类器提示词由三部分组成:系统提示词(定义分类器的角色和决策规则)、用户规则(用户定义的 allow/soft_deny/environment 规则)、操作上下文(当前操作的描述和历史对话)。

系统提示词定义了分类器的决策框架:优先考虑安全性,尊重用户规则,考虑操作上下文。用户规则通过 <user_allow_rules_to_replace><user_deny_rules_to_replace><user_environment_to_replace> 标签注入,这些标签在默认模板中包含默认规则,用户设置会替换这些默认值。

操作上下文包括工具名称、输入参数和相关的历史消息。对于 Bash 工具,系统提取命令描述,帮助分类器理解命令意图。分类器返回结构化响应,包括决策、置信度和理由。

Sources: utils/permissions/yoloClassifier.ts, utils/permissions/bashClassifier.ts

危险权限过滤

进入 auto 模式时,系统会剥离危险的权限规则,防止这些规则绕过分类器的安全评估。stripDangerousPermissionsForAutoMode 函数识别并移除以下危险规则:

  • 工具级别 Bash 允许规则BashBash(*),允许所有命令)
  • 脚本解释器前缀规则Bash(python:*)Bash(node:*) 等,允许执行任意代码)
  • Agent 和 REPL 工具的广泛允许规则(可能绕过内部工具的权限检查)
  • PowerShell 危险命令规则iexInvoke-ExpressionStart-Process 等)

被剥离的规则存储在 strippedDangerousRules 字段中,退出 auto 模式时通过 restoreDangerousPermissions 函数恢复。这确保了用户在 default 模式下的便利性规则不会危及 auto 模式的安全性。

Sources: utils/permissions/permissionSetup.ts, utils/permissions/dangerousPatterns.ts

权限 UI 组件与用户交互

权限 UI 系统负责向用户展示权限请求、收集用户决策和提供操作预览。系统为不同工具提供专门的 UI 组件,支持丰富的交互功能,包括快捷键、差异预览和持久化选项。

PermissionRequest 组件架构

PermissionRequest 是权限 UI 的核心组件,根据工具类型选择相应的专门组件。每个工具可以定义自己的权限请求 UI,通过 permissionComponentForTool 函数映射。例如,BashPermissionRequest 显示命令预览和安全警告;FileEditPermissionRequest 显示文件差异预览;WebFetchPermissionRequest 显示 URL 和请求参数。

ToolUseConfirm 对象封装了权限请求的所有信息:工具实例、输入参数、权限决策结果、回调函数(onAllowonRejectrecheckPermission)和状态标志(classifierCheckInProgressclassifierAutoApproved)。组件通过这些回调与权限系统交互,报告用户决策。

Sources: components/permissions/PermissionRequest.tsx

交互式权限流程

在交互式权限流程中,handleInteractivePermission 函数管理整个用户交互生命周期。函数首先将权限请求推入确认队列,显示权限对话框。同时,系统在后台异步执行权限钩子检查和 Bash 分类器检查,这些检查可能在用户响应之前自动批准请求。

为了防止竞态条件(用户交互和自动检查同时完成),系统使用 createResolveOnce 包装器确保只解析一次。userInteracted 标志跟踪用户是否已经开始交互(例如按下箭头键或输入文本),如果用户已交互,自动检查的结果会被忽略,尊重用户的主动参与。

权限对话框支持多种用户操作:Esc 取消请求,Enter 确认默认选项,Tab 在选项间切换,Ctrl+A 切换”始终允许”选项。用户可以选择允许一次、始终允许(持久化规则)、拒绝或提供文本/图片反馈。

Sources: hooks/toolPermission/handlers/interactiveHandler.ts

文件编辑权限预览

对于文件编辑工具(FileEditToolFileWriteTool),权限对话框显示详细的差异预览,帮助用户理解即将进行的更改。FileEditPermissionRequest 组件使用 StructuredDiff 组件渲染统一差异格式,支持语法高亮和行号显示。

预览系统还支持 IDE 集成,用户可以在 VS Code 或 JetBrains IDE 中打开差异视图。useFilePermissionDialog 钩子管理对话框状态,处理用户选择,并生成权限更新。对于 sed 编辑,系统在权限检查阶段应用模拟编辑,确保预览内容与实际写入内容完全一致。

Sources: components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx, components/permissions/FilePermissionDialog/FilePermissionDialog.tsx

权限上下文与状态管理

ToolPermissionContext 是权限系统的核心数据结构,封装了所有权限相关的状态,包括当前模式、规则集合、额外工作目录和模式特定的配置。该上下文通过 React 的 AppState 管理,支持跨组件共享和持久化。

ToolPermissionContext 结构

ToolPermissionContext 包含以下字段:mode(当前权限模式)、additionalWorkingDirectories(额外的工作目录映射)、alwaysAllowRulesalwaysDenyRulesalwaysAskRules(三个规则集合,按来源组织)、isBypassPermissionsModeAvailable(bypass 模式是否可用)、isAutoModeAvailable(auto 模式是否可用)、strippedDangerousRules(在 auto 模式下被剥离的危险规则)、shouldAvoidPermissionPrompts(是否避免权限提示,用于后台代理)、prePlanMode(进入 plan 模式前的模式,用于退出时恢复)。

上下文通过 getEmptyToolPermissionContext 函数初始化为默认值,通过 applyPermissionUpdate 函数更新,通过 transitionPermissionMode 函数切换模式。所有更新都是不可变的,返回新的上下文对象。

Sources: Tool.ts, types/permissions.ts

拒绝跟踪与回退机制

DenialTrackingState 跟踪分类器的拒绝次数,防止分类器陷入拒绝循环。系统维护两个计数器:consecutiveDenials(连续拒绝次数)和 totalDenials(总拒绝次数)。当连续拒绝达到 3 次或总拒绝达到 20 次时,shouldFallbackToPrompting 函数返回 true,系统回退到用户交互模式。

每次分类器拒绝操作时,recordDenial 函数递增计数器。当操作成功允许时,recordSuccess 函数重置连续拒绝计数器(保留总拒绝计数器)。这种机制确保了分类器在遇到不确定情况时会寻求用户帮助,而不是持续做出可能错误的决策。

Sources: utils/permissions/denialTracking.ts

工具集成与权限检查

每个工具通过实现 checkPermissions 方法参与权限系统。该方法接收输入参数和工具使用上下文,返回 PermissionResult 对象。工具可以根据自身语义实现专门的权限逻辑,例如文件工具检查路径是否在工作目录内,Bash 工具检查命令是否包含危险模式。

工具权限检查实现

BashTool 为例,checkPermissions 方法委托给 bashToolHasPermission 函数,该函数执行以下检查:只读约束检查(如果命令只读,自动允许)、沙箱检查(如果命令在沙箱外执行,需要用户确认)、复合命令拆分(拆分 &&; 连接的命令,分别检查)、规则匹配(应用 deny/allow/ask 规则)、安全检查(检测危险模式,例如 rm -rf /)。

工具可以通过 toAutoClassifierInput 方法定义如何将输入转换为分类器可理解的格式。对于 BashTool,该方法返回命令字符串;对于 FileEditTool,该方法返回编辑描述。分类器使用这些信息构建评估上下文。

Sources: tools/BashTool/BashTool.tsx, Tool.ts

权限上下文传递

工具使用上下文(ToolUseContext)包含权限上下文的访问器 getAppState,工具通过该访问器获取当前权限状态。上下文还包含 setToolPermissionContext 方法,用于更新权限状态(例如应用权限更新)。

对于子代理和异步任务,上下文包含 localDenialTracking 字段,用于本地拒绝跟踪(因为子代理的 setAppState 是空操作)。shouldAvoidPermissionPrompts 标志指示是否应该避免权限提示(例如后台代理无法显示 UI),在这种情况下,需要权限的操作会被自动拒绝。

Sources: Tool.ts, hooks/toolPermission/PermissionContext.ts

高级特性与扩展

沙箱集成与权限覆盖

当沙箱模式启用时,Bash 工具在隔离环境中执行命令。如果用户选择”在沙箱外运行”,权限系统创建 sandboxOverride 决策原因,记录用户的显式选择。沙箱外执行通常需要额外的权限确认,即使用户有相应的允许规则。

shouldUseSandbox 函数根据命令特征、用户设置和环境配置决定是否使用沙箱。某些命令(例如交互式命令、需要 TTY 的命令)不适合在沙箱中运行,系统会自动跳过沙箱。

Sources: tools/BashTool/shouldUseSandbox.ts, types/permissions.ts

Bridge 与远程权限

Bridge 系统支持远程权限请求,允许用户通过移动设备或其他客户端响应权限提示。BridgePermissionCallbacks 定义了远程权限交互的接口,包括 requestPermission 方法和 cancelPermissionRequest 方法。

当权限请求通过 Bridge 发送时,本地系统等待远程响应,同时继续处理本地用户交互。如果本地用户先响应,系统取消远程请求;如果远程响应先到达,系统使用远程决策。这种机制支持灵活的多设备工作流。

Sources: bridge/bridgePermissionCallbacks.ts, hooks/toolPermission/handlers/interactiveHandler.ts

权限解释与调试

permissionExplainer.ts 提供权限决策的解释功能,生成人类可读的决策原因描述。createPermissionRequestMessage 函数根据决策原因类型生成相应的消息:规则匹配时显示规则来源和内容,钩子拒绝时显示钩子名称和原因,子命令结果时列出需要批准的子命令。

PermissionDecisionDebugInfo 组件在开发模式下显示详细的决策信息,包括匹配的规则、决策路径和性能指标。这有助于调试权限问题和理解系统的决策逻辑。

Sources: utils/permissions/permissionExplainer.ts, components/permissions/PermissionDecisionDebugInfo.tsx

总结与最佳实践

Claude Code 的权限服务通过三层架构(模式、规则、分类器)实现了灵活而强大的访问控制。对于普通用户,建议使用 default 模式配合项目级别的允许规则,平衡安全性和便利性。对于高级用户,acceptEdits 模式可以加速文件编辑工作流,但应谨慎使用广泛规则。对于自动化场景,auto 模式(如果可用)提供了智能的自动化决策,但应监控拒绝跟踪指标,及时调整规则。

权限规则应遵循最小权限原则,优先使用具体的规则(例如 Bash(npm test))而不是广泛的规则(例如 Bash(npm:*))。定期审查持久化的权限规则,移除不再需要的规则。对于敏感项目,考虑使用策略设置强制执行权限策略,防止用户配置过于宽松的规则。