权限与沙箱:Claude Code 的双层防御体系
在 Claude Code 的安全哲学中,任何可能影响用户系统的操作都必须经过严密的合规性审查。这一审查并非单一的逻辑开关,而是由应用层的“权限引擎(Permissions)”与系统层的“物理沙箱(Sandboxing)”共同构建的双层纵深防御体系。
从定义开始
这套体系本质上是 “意图审计”与“物理隔离”的深度耦合。
- 权限引擎(第一层防线):回答的是“应不应该做”。它运行在 Claude 进程内部,像一个守门员,根据当前的运行模式(Default/Auto/Plan)、用户历史授权记录以及内置的安全策略,判断模型发起的工具调用请求是否合法。它不是简单的黑白名单,而是一个具备上下文感知能力的决策中心。
- 物理沙箱(第二层防线):回答的是“能不能做到”。它是底层的最后一道防线。即使权限引擎由于某种极端情况被绕过,沙箱也会通过操作系统内核特性(如 macOS 的 Sandbox 框架或 Linux 的 Namespace/Cgroups),为执行过程划定物理边界。
理解这两者的区别至关重要:权限系统管的是“不问你”,而沙箱管的是“不让动”。
运行时的真相
两层的协同工作流主要由权限裁决与环境装配两个阶段组成:
裁决阶段(Permission Decision Flow): 当模型发起工具请求(例如
BashTool)时,系统首先进入claude-code-opensource/src/utils/permissions/permissions.ts。- 上下文提取:系统提取
ToolPermissionContext,包括当前的 CWD、已添加的目录、以及用户通过/permissions配置的规则。 - 分流逻辑:如果命中白名单(只读工具)则放行;如果命中黑名单则拒绝;如果属于未知区域,则根据
PermissionMode(如default模式下弹窗,auto模式下查分类器)产生裁决结果。
- 上下文提取:系统提取
装配与隔离阶段(Sandbox Execution Flow): 一旦权限系统批准执行,且该操作被判定为“有副作用”或“不可信”,系统会通过
claude-code-opensource/src/utils/sandbox/sandbox-adapter.ts启动沙箱装配。- 配置动态生成:沙箱不是静态的。它会根据当前工作区、用户通过
/add-dir手动放行的路径,动态生成一份临时的配置文件(如 macOS 上的.sb文件)。 - 进程包裹:原始命令被包裹在沙箱启动器(如
sandbox-exec)中运行。此时,该进程只能看到被明确允许的文件路径,且默认无法访问网络。 - 异常捕获:如果进程尝试越界(Violation),操作系统会强制终止该操作,并将错误信息回传给
SandboxViolationStore记录。
- 配置动态生成:沙箱不是静态的。它会根据当前工作区、用户通过
双层同步逻辑: 每当用户执行
/add-dir时,系统会同步更新内存中的allowedDirectories,还会触发SandboxManager.refreshConfig()。这确保了应用层的“语义放行”能立即转化为系统层的“物理穿透”。
使用时的关键约束
- 隔离差异化:沙箱机制目前主要针对
BashTool产生的外部进程。对于 Claude 进程自身的 Node.js 逻辑(如FileEditTool或FileWriteTool),主要依靠第一层的权限引擎进行精确的路径校验(Path Validation)来防止越界。 - 物理限制的绝对性:即使你开启了
bypassPermissions模式(不再弹窗询问),沙箱层依然有效。如果模型尝试访问沙箱配置之外的系统文件,它依然会收到操作系统的EACCES错误。 - 网络默认隔离:除非在设置中显式开启了网络访问,否则沙箱内的所有进程均处于“离线”状态。这意味着
curl、wget等命令在没有用户配置的情况下会默认失败。 - 性能开销:在 Linux 环境下,由于沙箱依赖命名空间等特性,某些精简内核可能无法完全支持,此时系统会回退到纯权限检查模式并给出显著警告。
继续探索
- 如果你想了解 Claude 如何在无需人工干预的情况下智能识别安全操作,请阅读 Auto Mode:基于分类器的自动化审批。
- 如果你关心针对具体 Bash 命令(如管道、重定向)的语义扫描,请阅读 Bash 权限规则:语义匹配与风险拦截。
- 如果你想了解如何管理已经授予的权限,请参考 权限管理与规则配置:/permissions 详解。
源码锚点
- claude-code-opensource/src/utils/permissions/permissions.ts — 权限系统的核心入口,负责综合各种模式给出
Approve/Deny/Ask裁决。
📄 src/utils/permissions/permissions.ts — 权限系统的核心入口,负责综合各种模式给出 `Approve/Deny/Ask` 裁决。L30-33 of 1487
typescript
PermissionDenyDecision,
PermissionResult,
} from './PermissionResult.js'
import type {1
2
3
4
2
3
4
- claude-code-opensource/src/utils/sandbox/sandbox-adapter.ts — 沙箱适配层,屏蔽了不同操作系统(macOS/Linux)底层沙箱实现的差异。
📄 src/utils/sandbox/sandbox-adapter.ts — 沙箱适配层,屏蔽了不同操作系统(macOS/Linux)底层沙箱实现的差异。L489-493 of 986
typescript
* Supports: macOS, Linux, and WSL2+ (WSL1 is not supported)
*/
const isSupportedPlatform = memoize((): boolean => {
return BaseSandboxManager.isSupportedPlatform()
})1
2
3
4
5
2
3
4
5
- claude-code-opensource/src/tools/BashTool/shouldUseSandbox.ts — 判定逻辑:决定哪些 Bash 命令必须送入沙箱运行。
📄 src/tools/BashTool/shouldUseSandbox.ts — 判定逻辑:决定哪些 Bash 命令必须送入沙箱运行。L13-16 of 154
typescript
type SandboxInput = {
command?: string
dangerouslyDisableSandbox?: boolean
}1
2
3
4
2
3
4