摘要
如果把 Claude Code 理解为一个高权限的本地开发 Agent,那么其核心安全问题并不是“模型是否足够聪明”,而是三个更基础的问题:
- 谁在驱动这个 Agent;
- 每一个动作是否都经过了足够细粒度的约束;
- 系统是否能够区分“用户真实授权的意图”与“模型自行扩张出的执行冲动”。
从最新源码可以观察到,Claude Code 在这些问题上并非采用单一的权限弹窗机制,而是逐步形成了一套更接近零信任 Agent 控制平面的架构:
- 在身份层面,它尝试把账户、组织、设备、会话绑定成同一条信任链;
- 在执行层面,它把权限控制下沉到具体 Action / Tool Use,而不是只看会话级开关;
- 在高风险命令层面,尤其是 Bash,它引入了语法、语义、规则、分类器、人工确认的多阶段判定;
- 在意图层面,它不再只依赖静态 allowlist,而是引入了基于上下文转录的动作分类器,试图判断动作是否符合用户真实意图。
本文不把这些实现视为零散功能,而将其作为一套 Agent 安全架构进行分析。
一、问题定义:Agent 安全的核心,不是“能不能做”,而是“谁、何时、为何可以做”
传统 CLI 工具的安全边界相对简单:
- 使用者是明确的人;
- 操作入口是显式命令;
- 风险主要由操作系统权限和文件系统边界承担。
Agent 系统则不同。Claude Code 这类工具同时具备如下特征:
- 能直接读写代码仓库;
- 能执行 shell / PowerShell;
- 能启动子 Agent 或远程会话;
- 能在记忆、计划、调度等状态之间迁移;
- 能在“用户未逐字指定”的情况下,自主生成中间动作。
因此,其安全问题更接近如下形式:
一个具备高权限执行能力的自治体,如何在不完全牺牲交互效率的前提下,被持续约束在“人类意图可接受”的边界内?
从源码看,Claude Code 的回答不是“做一个更大的 confirmation dialog”,而是把控制拆成四层:
- 身份绑定层:确认是谁、属于哪个组织、来自哪个设备与会话;
- 动作授权层:每一次 tool use 都单独判定,而非一劳永逸放权;
- 高风险语义层:对 Bash 等危险表面做结构化分析;
- 意图判定层:用分类器判断动作是否符合真实任务意图。
这一点非常关键。它意味着 Claude Code 的安全模型已经从“静态权限管理”转向“运行时零信任判定”。
二、人-Agent 身份绑定:源码中已经出现账户、组织、设备、会话四元绑定的雏形
从研究角度看,Claude Code 安全体系中最值得注意的第一点,是它并未把 Agent 视为“匿名本地进程”。
相反,源码反复强调四类身份信息:
- 账户身份(account UUID / email);
- 组织身份(organization UUID);
- 设备身份(trusted device token);
- 会话身份(session ingress token / session ID)。
2.1 账户与组织绑定
在认证安装流程中,CLI 会持久化:
accountUuidorganizationUuidemailAddressdisplayName
这说明 Claude Code 并不是把“登录成功”当作单一布尔值,而是把人所属的组织上下文也纳入了本地信任状态。
从安全设计上看,这意味着后续很多动作可以不再只问“你有没有 token”,而是问:
- 这个动作对应哪个账户;
- 它是否属于正确组织;
- 跨组织上下文是否被错误复用。
2.2 会话入口绑定
session ingress auth 相关实现表明,会话接入并非裸连。
源码里存在明确的 session ingress token 读取逻辑,且支持:
- 通过环境变量注入;
- 通过文件描述符传递;
- 通过 well-known file 回退;
- 对不同 token 形态采用不同 header 方式。
尤其值得注意的是:当 token 形态属于 session-key 时,系统会额外注入 X-Organization-Uuid。
这意味着“会话可进入”并不是单纯的 bearer token 问题,而是被绑定到组织上下文中的。
2.3 设备绑定
更有研究价值的是 trusted device token。
在 bridge / remote-control 相关路径中,源码引入了:
- trusted device enrollment;
- 设备 token 持久化;
- elevated auth enforcement;
- 设备 token 与 bridge headers 的联动。
换言之,远程控制面并不是只信任“这个用户登录了”,而开始尝试回答:
发起高权限桥接请求的,是否还是那台被登记过的设备?
这一步非常像现代零信任系统中的 device posture 思路。
2.4 一个重要推论
综合这些机制可以推断:Claude Code 正在尝试把 Agent 的“执行人格”从抽象模型,收束到一条更具体的链路上:
人 → 账户 → 组织 → 设备 → 会话。
这条链路并不意味着系统已经彻底实现强身份不可抵赖,但至少说明它的设计方向不是“本地 Agent 天然可信”,而是“高权限 Agent 必须被具体身份上下文化”。
三、入向与出向权限检查:Claude Code 的控制点不是会话级,而是 Action 级
在安全系统中,“入向”和“出向”往往对应两个不同问题:
- 入向:外部请求是否可以进入 Agent 的执行面;
- 出向:Agent 想要调用工具、发起副作用时,是否应该被允许。
Claude Code 在这两端都已经出现了比较完整的结构。
3.1 入向:远程请求不是直接执行,而是先转译为权限请求对象
在 remote session 相关实现中,来自 CCR / remote side 的控制请求会被识别为 can_use_tool 类型,再进入本地 permission flow。
这意味着一个非常重要的边界被保留了:
远端并不能直接代表本地执行工具,而必须先把请求显式转换成“待授权的工具使用”。
这是一种典型的零信任姿态:
- 先假定远端执行意图不可信;
- 再将其转化为本地可审计、可拒绝、可取消的请求对象;
- 最终由本地控制面决定放行与否。
3.2 出向:每个 Tool Use 都进入 allow / ask / deny 决策机
在本地执行面,权限不是粗粒度地绑定到“本轮对话”或“当前 Agent 实例”,而是围绕每一次 tool use独立判断。
从类型与权限实现看,系统会给每个动作生成三类决策之一:
allowaskdeny
并伴随:
- 决策原因;
- 是否命中规则;
- 是否来自 classifier;
- 是否需要后续异步 classifier check;
- 是否附带建议规则更新。
这说明 Claude Code 的控制模型不是“先信任会话,再在内部自由行动”,而是:
把每次动作都视为一个独立的授权单元。
从零信任角度看,这比 session-level trust 更合理,因为 Agent 风险并不均匀:
- 读取文件与执行 shell 不是同一风险级别;
- 创建 task 与写系统目录不是同一风险级别;
- 调用子 Agent 与发起外部网络访问也不是同一风险级别。
四、Bash 是高风险表面的代表案例:Claude Code 采用了多阶段审查,而不是单点规则匹配
如果要观察 Claude Code 的安全设计最成熟的部分,Bash 是一个典型样本。
从源码看,Bash 权限判断不是一条简单正则,而是至少包含四个阶段。
4.1 第一阶段:危险语法与混淆模式识别
bashSecurity.ts 中存在大量针对 shell 绕过技巧的检测,包括但不限于:
- command substitution;
- process substitution;
- heredoc / quote desync;
- Zsh equals expansion;
- 反引号与参数展开;
- 变量注入、注释错位、控制字符等模式。
这些规则的意义并不在于“覆盖所有 shell 技巧”,而在于它已经承认:
对 Agent 而言,危险不只来自显式的
rm -rf,也来自各种能改变解释语义的 shell 变体与混淆写法。
这是一种明显高于普通命令白名单的安全建模。
4.2 第二阶段:语法 / 语义解析,而不仅是字符串匹配
Bash 权限实现并不只依赖文本模式,而会引入:
- AST / parser 结果;
- command prefix 提取;
- operator 权限检查;
- path constraints;
- sed 等特定命令约束。
也就是说,Claude Code 正尝试把 Bash 从“原始字符串”提升为“结构化动作”。
这一点非常重要。因为零信任控制只有在动作被结构化后,才可能做到Action-level,否则永远只能停留在 fragile 的字符串黑名单。
4.3 第三阶段:危险前缀规则剥离
permissionSetup.ts 中对 Bash / PowerShell / Agent 工具的危险规则做了专门清洗。
例如,以下类型的 broad allow 会被视为危险:
- 整个 Bash 全放行;
python:*/node:*/bash:*这类解释器级 broad prefix;ssh、env、xargs、sudo等可包装任意执行路径的前缀。
其背后的逻辑非常值得注意:
系统不只审查“动作本身”,还审查“用户给出的权限规则是否会让后续判定失效”。
这已经不是传统 ACL,而是一种“对授权机制本身做安全检查”的设计。
4.4 第四阶段:分类器与人工审批兜底
即便经过前述规则与解析,Bash 仍可能进入:
- 异步 classifier check;
- 用户交互审批;
- 远端 / 通道审批竞态;
- deny tracking 与 fallback 机制。
也就是说,Claude Code 并不假定静态规则足够完备,而是把 Bash 视为一个需要持续判定与人工兜底的风险表面。
从安全研究角度看,这是合理的。因为 shell 语言的表达能力决定了它很难被完全静态封闭。
五、Action 级零信任:其核心不是“默认拒绝”,而是“默认重新验证”
很多系统提到零信任时,会简单地把它概括为“默认拒绝”。
但从 Claude Code 的实现看,更准确的描述是:
默认不把任何一次高风险动作视为可被永久继承的信任。
这一点体现在几个细节上。
5.1 safe allowlist 是严格受限的
在 auto mode classifier 决策中,真正被放进 safe allowlist 的,多为:
- 只读读取类工具;
- 搜索类工具;
- 任务元数据管理;
- team / message / orchestration 的内部状态操作。
甚至源码里还明确强调:
- team coordination 不等于安全绕过;
- subagent 仍然需要各自独立的权限检查。
这说明系统并未因为“这是内部编排动作”就整体放权,而是坚持把执行副作用与编排元操作区分开。
5.2 第一响应者获胜(first resolver wins)
在交互权限处理、bridge、channel relay 等路径里,可以看到一个一致思想:
- hook、classifier、本地 UI、远端桥接、通道审批之间存在竞态;
- 但系统通过
claim()/ resolve-once 机制保证只有第一个合法决策生效。
这是一种很典型的分布式安全思路:
在多控制面并存时,必须定义唯一生效的授权提交语义,否则会出现双重批准、状态不同步或被后写覆盖的漏洞。
5.3 远端/通道审批不是对话文本,而是结构化事件
通道权限中最值得肯定的一点,是审批并不是“用户说一句 yes”。
相反,审批回复会被要求经由服务器解析后,转换为特定结构化事件,再由本地匹配 request_id 生效。
这等于把“聊天文本”与“安全指令”分离开来。
从零信任角度,这是必要的:
- 普通对话文本不应该天然具有授权能力;
- 授权必须是被明确编码、明确关联请求、明确落到特定 resolver 的控制事件。
六、意图判断:Claude Code 已经开始把“用户真实意图”作为独立安全信号
用户特别关心的“基本意图判断能力”,在 Claude Code 中并不是空白。
从 yoloClassifier.ts 可以看到,系统已经在做一件很重要的事:
不只检查命令危险性,还试图判断该动作是否符合当前任务与用户真实意图。
6.1 分类对象不是单条命令,而是动作与上下文的组合
formatActionForClassifier、转录构造与工具输入投影表明,分类器输入不是孤立命令,而是由以下信息共同构成:
- 用户消息;
- assistant 的 tool_use 历史;
- 经过投影后的工具输入;
- CLAUDE.md 配置;
- auto mode 的 allow / soft_deny / environment 规则。
这意味着 Claude Code 试图回答的问题不是:
rm危险不危险?
而是:
在当前任务、当前上下文、当前环境约束下,这个动作是否符合用户想让 Agent 做的事情?
这正是意图判断的雏形。
6.2 系统有意识地排除了容易污染分类器的内容
源码里一个很值得注意的细节是:构造 transcript 时,会有意识地排除 assistant 自己的自由文本,主要保留 user 文本与 tool_use 轨迹。
这背后的安全含义很直接:
- assistant 自己生成的解释文本,可能反过来“说服分类器”批准自己的动作;
- 若分类器读取了大量模型自述,就有可能形成自我强化回路。
因此,Claude Code 在这里做了一个很重要的隔离:
让意图判定尽量依赖用户输入和客观动作轨迹,而不是模型自我辩护。
6.3 fail-closed 倾向非常明显
无论是 XML 两阶段判定,还是 response parse 路径,都可以看到一个明确倾向:
- 若 classifier 结果不可解析;
- 若 classifier 请求中断;
- 若上下文过长导致异常;
- 若未拿到预期结构化结果;
系统会偏向 shouldBlock: true 或回退到人工 prompt。
这说明 Claude Code 在意图判定层面采用的是典型的fail-closed / fail-safe策略,而不是“判不清就默认继续做”。
6.4 但这仍然只是“基本意图判断”,不是强语义理解
需要保持克制的是:从源码来看,当前实现更像是安全分类器驱动的风险判定,而非完整意义上的 intent verifier。
原因包括:
- 它仍以规则模板和启发式上下文为主;
- classifier 在不同 build / gate 下能力并不一致;
- 对长链条、多阶段代理目标的语义一致性验证仍较弱;
- 远不能证明“动作严格等价于用户主观意图”。
因此,更准确的表述是:
Claude Code 已经在实现“面向意图的安全近似判定”,而不是“完备意图理解”。
七、一个值得重视的研究结论:Claude Code 正在形成“身份 + 动作 + 意图”三位一体的 Agent 安全架构
综合前述分析,可以把 Claude Code 当前显露出的安全设计总结为三层耦合结构:
7.1 身份层:谁在驱动系统
- 账户
- 组织
- 设备
- 会话
这一层解决的是:谁有资格进入 Agent 控制面。
7.2 动作层:系统具体要做什么
- Tool Use 独立授权
- Bash / PowerShell 高风险语义检查
- 规则来源区分(用户、项目、本地、策略、会话等)
- 远端、通道、本地 UI 的结构化审批
这一层解决的是:每一个副作用动作能否被允许执行。
7.3 意图层:这个动作是否符合人类真实授权边界
- transcript-based classifier
- allow / soft_deny / environment 模板
- fail-closed 输出约束
- assistant 文本污染隔离
这一层解决的是:为什么这个动作此刻可以被视为合理。
对 Agent 安全而言,这种三层结构比单纯 RBAC 更接近现实需求。因为高权限 Agent 的风险不只来自“没有权限”,还来自:
- 身份借位;
- 权限被过度继承;
- 工具表达能力超出规则粒度;
- 模型把模糊任务自行扩展成高风险动作。
八、局限与开放问题:它已经有零信任形态,但距离强安全 Agent 仍有距离
从研究视角看,Claude Code 的这些设计值得肯定,但也应看到其边界。
8.1 身份绑定仍然偏平台内闭环
当前身份链条很大程度仍依赖:
- OAuth 账户体系;
- Anthropic 自身组织上下文;
- trusted device token;
- session token 管理。
这意味着它对第三方企业 IAM、设备姿态、审计总线的原生整合仍有限。
8.2 意图判断仍是概率性,不是形式化验证
无论 classifier 做得多好,本质仍是近似判断器。
它可以降低误操作概率,但不能形式化证明:
- 用户目标与执行计划完全一致;
- 子 Agent 行为不会目标漂移;
- 多步链条组合后仍满足原始授权。
8.3 零信任执行仍主要集中在工具入口,而不是结果约束
目前观察到的控制点大多发生在:
- tool use 之前;
- 远端请求进入本地之前;
- classifier 输出动作建议之前。
但对于“执行结果是否偏离预期”“子步骤组合后是否构成新的高风险状态”,源码层面的结果验证能力仍相对有限。
九、结论:这不是一个简单的权限弹窗系统,而是一套正在成型的 Agent 安全控制平面
如果只从产品表面看,Claude Code 的权限系统容易被理解成:
- 一些 allow / deny 规则;
- 一个 Bash 风险检测器;
- 再加若干确认弹窗。
但从源码整体观察,更准确的描述应当是:
Claude Code 正在构建一套以身份绑定、动作级授权和意图判定为核心的 Agent 安全控制平面。
它的关键特征不是“是否有一个按钮让你点同意”,而是:
- 将信任从会话级下沉到 action 级;
- 将授权从静态规则扩展到运行时判定;
- 将安全边界从“命令是否合法”推进到“动作是否符合用户意图”;
- 将高权限 Agent 重新置于可审计、可取消、可竞态仲裁的控制结构中。
从安全研究视角看,这一设计方向比“更强的 Agent”本身更值得关注。
因为未来真正决定 Agent 能否进入企业核心工作流的,未必是它会不会写代码,而是它能否被证明:
- 绑定到具体的人;
- 约束到具体的动作;
- 并尽可能忠实于人的真实意图。
Claude Code 至少已经把这件事,当成了一个一等公民问题来处理。
评论