权限与安全
Claude Code 的权限模型、评估管道与沙箱机制
权限模式
六种运行模式,从严格到宽松
Default
标准权限模式,所有工具调用都需要用户确认
每个工具调用都会弹出确认提示,用户手动决定 Allow、Deny 或 Allow Always。适用于对安全性要求最高的场景。
Plan
计划模式,只读操作自动允许,写操作需要确认
文件读取、搜索等只读操作自动放行,文件写入、命令执行等修改操作仍需确认。适合代码审查和探索阶段。
Auto Edit
自动接受文件编辑,但命令执行仍需确认
FileEdit、FileWrite 等文件编辑工具自动批准,BashTool 等命令执行工具仍需确认。平衡效率与安全。
Accept Edits
自动接受文件系统操作(mkdir, touch, rm, mv, cp, sed)
在 BashTool 中,文件系统相关命令(mkdir、touch、rm、rmdir、mv、cp、sed)自动允许,其他命令仍走标准权限流程。
Don't Ask (Auto-Approve)
自动批准所有工具调用,无需确认
所有工具调用自动批准,不弹出任何确认提示。最高效率但最低安全性,适合受信任的自动化流水线。
Bypass Permissions
完全绕过权限系统,所有操作直接执行
跳过所有权限检查和分类器评估。仅用于高度受控的环境(如 CI/CD),普通开发中不建议使用。
模式对比
不同模式下的权限行为一览
| 模式 | 文件读取 | 文件编辑 | Bash 命令 | 安全级别 |
|---|---|---|---|---|
| Default | Ask ✋ | Ask ✋ | Ask ✋ | 🟢 最高 |
| Plan | Allow ✅ | Ask ✋ | Ask ✋ | 🟢 高 |
| Auto Edit | Allow ✅ | Allow ✅ | Ask ✋ | 🟡 中 |
| Accept Edits | Allow ✅ | Allow ✅ | Ask ✋ | 🟡 中 |
| Don't Ask | Allow ✅ | Allow ✅ | Allow ✅ | 🔴 低 |
| Bypass | Allow ✅ | Allow ✅ | Allow ✅ | ⚪ 无 |
权限评估管道
每个工具调用经过的多阶段权限检查
① 模式检查
首先检查当前权限模式(default/plan/acceptEdits 等)。模式可以 直接决定某些操作的行为,例如 Plan 模式自动放行只读操作, Accept Edits 模式自动放行文件系统命令。
② 规则匹配
检查用户自定义的权限规则(Permission Rules)。支持精确匹配、前缀匹配和通配符模式。 匹配到的规则直接决定 allow 或 deny,未匹配则传递给分类器。
③ 分类器评估
Bash Classifier 对 shell 命令进行语义分析,区分只读命令(ls、cat、grep) 和潜在危险命令(rm、curl、npm install),自动做出安全决策。
核心类型定义
来自 claude-code 源码的真实类型
// types/permissions.ts — 权限模式定义
// 外部可见的权限模式(用户可配置)
export const EXTERNAL_PERMISSION_MODES = [
'acceptEdits', // 自动接受文件系统操作
'bypassPermissions', // 完全绕过权限系统
'default', // 标准模式,所有操作需确认
'dontAsk', // 自动批准所有操作
'plan', // 计划模式,只读自动放行
] as const
// 内部扩展模式
export type InternalPermissionMode =
| ExternalPermissionMode
| 'auto' // 智能自动决策(Transcript Classifier)
| 'bubble' // 权限决策冒泡给上层
// 权限行为
export type PermissionBehavior = 'allow' | 'deny' | 'ask'
// 权限决策结果
export type PermissionResult = {
behavior: PermissionBehavior
message?: string
decisionReason?: {
type: 'mode' | 'rule' | 'classifier' | 'sandbox'
mode?: PermissionMode
}
}沙箱机制
隔离执行不可信命令的安全容器
🔒 沙箱决策逻辑
- 1.检查
SandboxManager.isSandboxingEnabled()— 全局开关 - 2.检查
dangerouslyDisableSandbox— 显式覆盖 - 3.检查排除列表 — 用户配置的排除命令(支持前缀/通配符)
- 4.通过所有检查 → 在容器中执行;否则 → 本地执行
⚠️ 安全边界说明
- 排除命令 ≠ 安全边界:排除列表是用户便利功能, 不是安全控制。绕过排除列表不构成安全漏洞。
- 真正的安全控制:沙箱权限系统(弹出用户确认) 才是实际的安全边界。
- 复合命令处理:对
cmd1 && cmd2格式, 逐个拆分子命令检查,防止通过复合命令逃逸沙箱。
Bash 命令分类器
基于语义分析的自动权限决策
// utils/permissions/bashClassifier.ts
// 分类器行为
type ClassifierBehavior = 'allow' | 'deny' | 'ask'
// 分类结果
type ClassifierResult = {
matches: boolean
confidence: number // 0-1 置信度
reason: string // 决策理由
matchedDescription?: string
}
// 分类器描述 — 定义命令模式与行为映射
getBashPromptAllowDescriptions() // 自动允许的命令描述
getBashPromptAskDescriptions() // 需要确认的命令描述
getBashPromptDenyDescriptions() // 自动拒绝的命令描述
// 示例分类:
// ✅ Allow: ls, cat, grep, head, tail, find, wc, echo ...
// ❌ Deny: rm -rf /, sudo, chmod 777 ...
// 🤔 Ask: curl, wget, npm install, docker ...权限规则系统
用户自定义的细粒度权限控制
规则类型
精确匹配命令字符串,如 ls
前缀匹配,如 npm * 匹配所有 npm 命令
通配符模式,如 git push *
规则值
Undercover 模式
安全贡献公共仓库时的隐私保护
什么是 Undercover 模式?
Undercover 模式是 Claude Code 内部使用的安全机制,当贡献到公共/开源仓库时自动激活。 它会在 commit 和 PR 提示中添加安全指令,并移除所有可能泄露内部信息的归属标记。
🔧 激活方式
CLAUDE_CODE_UNDERCOVER=1— 强制开启- 默认 AUTO:仓库 remote 不在内部白名单中时自动激活
- 没有强制关闭选项(安全设计)
🛡️ 保护内容
- 模型代号(不告诉模型它是什么模型)
- 内部项目名称和代号
- Anthropic 内部信息
- commit/PR 中的归属标记
💡 了解更多 Undercover 模式的实际应用,请访问 /buddy 页面。
远程权限桥接
Remote Permission Bridge
// remote/remotePermissionBridge.ts
// 当工具在远程 CCR 容器中执行时,本地 CLI 需要处理权限请求。
// 由于本地没有真实的 AssistantMessage,需要创建合成消息。
function createSyntheticAssistantMessage(
request: SDKControlPermissionRequest,
requestId: string,
): AssistantMessage {
return {
type: 'assistant',
message: {
role: 'assistant',
content: [{
type: 'tool_use',
id: request.tool_use_id,
name: request.tool_name,
input: request.input,
}],
},
// ...
}
}
// 对于本地未知的远程工具(如 MCP 工具),创建工具存根
function createToolStub(toolName: string): Tool {
return {
name: toolName,
needsPermissions: () => true,
isReadOnly: () => false,
// ...
}
}Accept Edits 模式验证
modeValidation.ts — 基于模式的命令验证
// tools/BashTool/modeValidation.ts
// Accept Edits 模式下自动允许的文件系统命令
const ACCEPT_EDITS_ALLOWED_COMMANDS = [
'mkdir', 'touch', 'rm', 'rmdir', 'mv', 'cp', 'sed',
] as const
function validateCommandForMode(
cmd: string,
toolPermissionContext: ToolPermissionContext,
): PermissionResult {
const [baseCmd] = cmd.trim().split(/\s+/)
// Accept Edits 模式 → 自动允许文件系统操作
if (
toolPermissionContext.mode === 'acceptEdits' &&
isFilesystemCommand(baseCmd)
) {
return {
behavior: 'allow',
updatedInput: { command: cmd },
decisionReason: { type: 'mode', mode: 'acceptEdits' },
}
}
// Bypass 模式在主权限流中处理
return { behavior: 'passthrough' }
}