Auto Mode:基于智能分类与沙箱信任的自动化审批
Auto Mode(自动模式)是 Claude Code 权限架构中最体现设计智慧的部分。它并不是简单地关闭权限检查,而是引入了一个基于小模型的“分类器流水线”和“物理沙箱信任机制”,来替人类进行初步的安全合规性裁决。
核心概念
Auto Mode 本质上是 审批权的动态代理(Delegated Decision Making)。
它旨在解决开发者面临的“审批疲劳”问题:如果每一个只读操作(如读文件、列出目录)都要用户点击确认,那么开发效率将大打折扣。
- 它不是什么:它不是“全能绿灯”。它依然拥有一套严密的拦截准则,针对高风险、不可逆的操作(如跨目录修改、敏感网络连接、特权命令),它会自动降级回人工审批。
- 它的核心理念:将人类的时间花在关键决策上,将琐碎的合规性判断交给分类器(YOLO)和受物理隔离保护的沙箱。
代码里的真实逻辑
Auto Mode 的决策链由 claude-code-opensource/src/utils/permissions/classifierDecision.ts 核心驱动,遵循一个“三级阶梯式”的审批逻辑:
1. 静态白名单(Static Allowlist)
为了极致的响应速度,系统硬编码了一份 SAFE_YOLO_ALLOWLISTED_TOOLS。所有只读类工具(FileRead、Grep、Glob)、任务状态管理工具(TaskCreate、TaskList)以及 UI 辅助工具都会命中此名单。这些操作被认为是绝对安全的,直接跳过任何判断逻辑,无感放行。
2. 分类器裁决(The YOLO Classifier)
对于超出白名单但又属于“常规开发”范畴的操作,系统会启动 yoloClassifier.ts(也被称为 YOLO 模型)。这是一个轻量化的分类器,它会迅速扫描模型当前的上下文:
- 输入流:即将执行的命令(如
npm run build)、当前任务的目标、以及最近的操作历史。 - 判定流:它会基于预设的安全策略给出三色裁决:
Approve(自动执行)、Deny(告知模型被拒绝)或Ask(升级给人类用户)。 - 熔断机制:通过
denialTracking.ts监控拒绝次数。如果模型在 Auto 模式下短时间内连续触发拒绝,系统会强行中断自动化流程,防止模型陷入无效重试的死循环。
3. 沙箱信任锚点(Sandbox Auto-Allow)
这是 Auto Mode 逻辑的深度补充。在执行 Bash 命令时,系统会调用 checkSandboxAutoAllow:
- 逻辑转换:如果当前环境已经开启了物理沙箱(OS-level isolation),且用户配置了
autoAllowBashIfSandboxed,系统会认为:“既然这个命令已经在被隔离的沙箱中运行,无法触碰核心系统,那么我们可以自动放行”。 - 显式优先原则:即使处于沙箱环境,如果用户之前通过
/permissions手动设置了针对该命令的Deny或Ask规则,沙箱自动放行逻辑会立即失效。用户的显式意愿永远高于系统的自动猜测。
别踩这些坑
- 路径隔离(CWD Constraint):大部分自动放行仅限于当前 CWD(工作目录)。如果模型尝试修改用户目录之外的文件,即使在 Auto Mode 下也会触发显式的权限询问。
- 风险分级:
sudo命令、涉及rm -rf的全局删除、未经声明的网络请求(如向未知域名发送数据)属于高风险分级,分类器几乎总是会将其路由到Ask状态。 - 身份敏感性:源码显示,Auto Mode 的某些高级逻辑(如基于 Transcript 的精细分类)带有
ant用户标签检测。这意味着不同版本的 Claude Code(如企业版 vs 个人版)在自动化激进度上可能存在微调。 - 沙箱完整性依赖:Sandbox Auto-Allow 的安全性完全依赖于操作系统的沙箱实现。如果沙箱本身配置有误或由于系统限制未生效,该功能会自动关闭以确保安全。
相关主题
- 如果你想了解如何彻底消除所有审批干扰,请看 Bypass Permissions:危险的执行绿灯。
- 如果你想了解物理沙箱的具体实现逻辑,请看 权限与沙箱:双层防御体系。
- 如果你想知道 Bash 命令是如何在语义层面被拆解审计的,请看 Bash 权限规则:语义匹配与风险拦截。
源码锚点
- claude-code-opensource/src/utils/permissions/classifierDecision.ts:56 —
SAFE_YOLO_ALLOWLISTED_TOOLS:内置的免审白名单。
📄 src/utils/permissions/classifierDecision.ts — `SAFE_YOLO_ALLOWLISTED_TOOLS`:内置的免审白名单。L56-85 of 99
typescript
const SAFE_YOLO_ALLOWLISTED_TOOLS = new Set([
// Read-only file operations
FILE_READ_TOOL_NAME,
// Search / read-only
GREP_TOOL_NAME,
GLOB_TOOL_NAME,
LSP_TOOL_NAME,
TOOL_SEARCH_TOOL_NAME,
LIST_MCP_RESOURCES_TOOL_NAME,
'ReadMcpResourceTool', // no exported constant
// Task management (metadata only)
TODO_WRITE_TOOL_NAME,
TASK_CREATE_TOOL_NAME,
TASK_GET_TOOL_NAME,
TASK_UPDATE_TOOL_NAME,
TASK_LIST_TOOL_NAME,
TASK_STOP_TOOL_NAME,
TASK_OUTPUT_TOOL_NAME,
// Plan mode / UI
ASK_USER_QUESTION_TOOL_NAME,
ENTER_PLAN_MODE_TOOL_NAME,
EXIT_PLAN_MODE_TOOL_NAME,
// Swarm coordination (internal mailbox/team state only — teammates have
// their own permission checks, so no actual security bypass).
TEAM_CREATE_TOOL_NAME,
// Agent cleanup
TEAM_DELETE_TOOL_NAME,
SEND_MESSAGE_TOOL_NAME,
// Workflow orchestration — subagents go through canUseTool individually
...(WORKFLOW_TOOL_NAME ? [WORKFLOW_TOOL_NAME] : []),1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- claude-code-opensource/src/utils/permissions/yoloClassifier.ts — 自动化分类器的核心 Prompt 与逻辑。
📄 src/utils/permissions/yoloClassifier.ts — 自动化分类器的核心 Prompt 与逻辑。L37-40 of 1496
typescript
getBashPromptAllowDescriptions,
getBashPromptDenyDescriptions,
} from './bashClassifier.js'
import {1
2
3
4
2
3
4
- claude-code-opensource/src/tools/BashTool/bashPermissions.ts:1270 —
checkSandboxAutoAllow:基于沙箱环境的自动放行算法。
📄 src/tools/BashTool/bashPermissions.ts — `checkSandboxAutoAllow`:基于沙箱环境的自动放行算法。L1270-1299 of 2622
typescript
function checkSandboxAutoAllow(
input: z.infer<typeof BashTool.inputSchema>,
toolPermissionContext: ToolPermissionContext,
): PermissionResult {
const command = input.command.trim()
// Check for explicit deny/ask rules on the full command (exact + prefix)
const { matchingDenyRules, matchingAskRules } = matchingRulesForInput(
input,
toolPermissionContext,
'prefix',
)
// Return immediately if there's an explicit deny rule on the full command
if (matchingDenyRules[0] !== undefined) {
return {
behavior: 'deny',
message: `Permission to use ${BashTool.name} with command ${command} has been denied.`,
decisionReason: {
type: 'rule',
rule: matchingDenyRules[0],
},
}
}
// SECURITY: For compound commands, check each subcommand against deny/ask
// rules. Prefix rules like Bash(rm:*) won't match the full compound command
// (e.g., "echo hello && rm -rf /" doesn't start with "rm"), so we must
// check each subcommand individually.
// IMPORTANT: Subcommand deny checks must run BEFORE full-command ask returns.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- claude-code-opensource/src/utils/permissions/denialTracking.ts — 防止自动化陷入死循环的熔断机制。
📄 src/utils/permissions/denialTracking.ts — 防止自动化陷入死循环的熔断机制。L7-10 of 46
typescript
export type DenialTrackingState = {
consecutiveDenials: number
totalDenials: number
}1
2
3
4
2
3
4