推荐标题:Claude Code 权限分析器为什么必须 Fail Closed 备选标题1:别只看表面:Claude Code 权限分析器为什么必须 Fail Closed真正要验收什么 备选标题2:一张工程图拆解 Claude Code 权限分析器为什么必须 Fail Closed 备选标题3:Claude Code 权限分析器为什么必须 Fail Closed为什么经常被理解错

权限分析器看不懂命令时必须拒绝或升级审批

摘要

摘要

Claude Code v2.1.214 在一个版本中修复了多种权限分析边界:路径 Glob 错误匹配、Windows PowerShell 5.1 Permission Check Bypass、Bash 文件描述符重定向解析差异、zsh 条件表达式中的变量修饰符、远程 Daemon 参数、超长命令和本地/远程 Session 审批时序。v2.1.215 随后停止自动运行 /verify/code-review,改为显式调用。[S1]

这些修复不能被简单概括为“加了几个黑名单”。它们说明 Coding Agent 的权限系统面对的是编译器前端与 Policy Engine 的组合问题:原始字符串必须按目标 Shell 解析、规范化、识别副作用,再与规则和运行时隔离进行联合决策。

最重要的安全不变量是:

Analyzer Can Prove Safe  → Auto Allow
Analyzer Is Unsure       → Ask
Analyzer Detects Risk    → Deny or Sandbox

任何 Unknown Syntax → Assume Harmless 都是在把解析器的不确定性转化为执行权限。

1. 权限分析器真正要判断什么

用户批准的不是一串字符,而是一个预期语义:读取某个文件、运行某个测试、连接某个服务或修改某个目录。Shell 接收字符后还会执行:

  • Tokenization;
  • 引号和转义;
  • 变量展开;
  • Glob;
  • 命令替换;
  • 重定向;
  • 管道和条件执行;
  • 子 Shell;
  • 平台特定语法;
  • 外部命令自身的参数解析。

权限分析器若只做字符串前缀匹配,可能把“看起来只读”的命令交给 Shell,而 Shell 执行的是另一套语义。

2. v2.1.214 暴露的五类边界

2.1 路径作用域与 Canonicalization

Edit(src/**) 曾可能自动批准项目树中其他位置的同名嵌套目录。根因不是 src 这个字符串,而是规则中的相对路径应绑定哪个基准目录。

安全评估需要先确定:

Rule Path
→ Resolve Against CWD / Project Root
→ Normalize . and ..
→ Resolve Symlink Policy
→ Compare Canonical Target

同名目录、Git Worktree、Symlink、Hard Link 和 Bind Mount 都会让“逻辑路径”与“实际对象”分离。

2.2 Bash 重定向与解析差异

Bash 的文件描述符重定向、复合命令和条件组合可以改变数据流和副作用。Release 明确说明,某些 FD Redirect 形式在 Claude Code 与 Bash 中解析不同,因此改为 Fail Closed。[S1]

关键不是枚举全部危险字符,而是建立 Parser Differential:

  1. 权限分析器输出规范化 AST;
  2. 目标 Shell 输出自己的解析结果;
  3. 两者不能证明等价时,不自动放行。

2.3 PowerShell 版本与不可见语义

PowerShell 5.1 与 PowerShell 7 在解析、编码和命令行为上并不完全一致。Release 确认修复了 Windows PowerShell 5.1 的 Permission Check Bypass。[S1] 后续版本还继续处理不可见 Unicode 和网络路径等边界。

权限判断必须绑定:

  • Shell 类型;
  • Shell 版本;
  • 操作系统;
  • 编码;
  • 执行策略;
  • 当前 Provider 和路径语义。

“PowerShell 命令”不是一个稳定语法集合。

2.4 远程 Daemon 改变执行边界

Docker、Podman 等命令看似在操作本地容器,但 --url--connection--identity 或远程模式可能把操作发送到另一台主机。权限系统如果只按命令名分类,会把本地风险模型错误应用到远程资产。

需要把目标执行域纳入 Policy:

Local CLI
→ Endpoint Resolution
→ Local / Remote / Unknown
→ Identity and Credential
→ Resource Scope
→ Approval Decision

2.5 审批时序与 Remote Session

Release 还修复了远程 Session 的权限请求可能早于本地确认继续执行的问题。[S1] 这属于分布式状态机:请求、展示、确认、执行和审计必须具有一致顺序,不能让两个 Session 对同一次操作形成不同状态。

3. 官方权限模型给出的基础框架

3. 官方权限模型给出的基础框架

Claude Code 官方文档把权限规则分为 denyaskallow,评估顺序为:

Deny → Ask → Allow

第一条匹配规则决定结果;权限由 Claude Code 执行,而不是由模型自行决定。[S2]

这带来三个设计结论:

  1. Prompt、CLAUDE.md 或 AGENTS.md 只能表达行为偏好,不能替代执行权限。
  2. Deny 是硬边界,Ask 是人工节点,Allow 只应覆盖可证明的低风险范围。
  3. 规则顺序、范围和路径基准都必须可测试。

官方 Sandbox 文档进一步说明,Bash 执行可使用 OS 级文件系统和网络隔离。[S3] 权限分析与 Sandbox 不是替代关系:

  • Analyzer 决定是否允许尝试;
  • Sandbox 限制即使执行也能触达的资源;
  • Audit 记录实际发生了什么。

4. 正确的控制平面

Raw Command

Shell and Version Selection

Shell-Aware Parser

Normalized AST

Path / Endpoint Resolution

Side-Effect Classification

Policy Evaluation: Deny / Ask / Allow

OS Sandbox and Credential Scope

Execution

Runtime Audit and Result Classification

4.1 Shell-Aware Parser

至少输出命令、参数、重定向、管道、条件分支、子命令和变量引用。不能理解的节点标记为 UNKNOWN,而不是丢弃。

4.2 Side-Effect Classification

副作用不只分读写。建议分类:

  • 本地只读;
  • 本地写入;
  • 删除或不可逆;
  • 网络访问;
  • 凭据访问;
  • 进程/服务控制;
  • 容器/虚拟化控制;
  • 远程执行;
  • 代码加载;
  • 未知。

4.3 Policy Evaluation

Policy 需要同时引用:

  • 规范化 AST;
  • Canonical Path;
  • Endpoint;
  • Tool Source;
  • Session/用户身份;
  • Repository Trust;
  • Sandbox Profile;
  • 风险等级。

4.4 Runtime Audit

OpenTelemetry 中增加 message.uuidclient_request_idtool_source,为把模型消息、用户请求与工具来源串成 Trace 提供了基础。[S1] 企业审计应进一步记录:

  • 决策规则 ID;
  • 原始与规范化命令哈希;
  • 批准者;
  • Sandbox Profile;
  • 实际文件和网络副作用;
  • Exit Code;
  • 结果摘要;
  • 回滚状态。

5. Fail Closed 不等于所有命令都弹窗

Fail Closed 的目标不是制造审批疲劳,而是让不确定语义不能自动跨越权限边界。

更合理的三层策略:

可证明安全

例如固定工作区内的明确只读操作、无网络、无外部脚本加载、无重定向。可自动允许。

不确定

含未知语法、超长命令、动态变量、远程目标、复杂重定向、命令替换。转入 Ask。

明确高风险

删除、凭据导出、远程 Daemon、宿主机 Socket、系统目录写入、执行下载内容。Deny 或只在隔离环境中允许。

减少弹窗的正确方法是缩小 Agent 能力面、提供更精确的 Tool、使用预批准的任务模板和强 Sandbox,而不是把未知语法默认安全。

6. Approval Fatigue

6. Approval Fatigue

Ask 不是万能控制。用户可能连续点击批准,甚至无法从长命令中识别真实副作用。审批界面必须展示“语义摘要”,而不是只展示原始字符串:

Action: Write files
Scope: /workspace/src/**
Network: none
Credentials: none
Remote target: none
Irreversible: no
Reason: run formatter on generated files
Policy: ask-write-workspace

对复杂命令,界面还应显示展开后的路径、远程端点、重定向目标和外部脚本来源。

7. 跨 Shell 回归测试

Permission Analyzer 应拥有类似编译器的测试矩阵:

维度示例
ShellBash、zsh、PowerShell 5.1、PowerShell 7
OSLinux、macOS、Windows
Path相对、绝对、..、Symlink、UNC、Worktree
Syntax引号、变量、重定向、管道、条件、子命令
Endpoint本地、远程、未知
Length正常、超长、截断边界
EncodingASCII、Unicode、不可见字符
ExpectedAllow、Ask、Deny、Parse Error

测试必须同时断言:规范化 AST、副作用分类、规则匹配和最终决策。

8. 与 MCP 和 Plugin Trust 的共同模型

8. 与 MCP 和 Plugin Trust 的共同模型

命令审批和 MCP/Plugin Trust 共享同一个原则:批准对象必须是可识别的具体工件,而不是一个永久可信的名字。

Code / Config / Assets
→ Canonical Manifest
→ Fingerprint
→ Approval Record
→ Runtime Verification
→ Allow / Reapprove / Block

权限规则、Plugin 版本、MCP 资源和 Sandbox Profile 都应进入审批记录。任何影响执行语义的变化都应触发重新评估。

9. 不能从 Release 推出的结论

  • 没有证据说明每项修复都曾被真实攻击者利用。
  • 没有找到对应 CVE 或公开 Security Advisory。
  • 不能用“Bypass”一词自动推断严重等级。
  • Ask Prompt 不能阻止用户无差别批准。
  • Parser 修复不能替代 Sandbox、最小权限和网络隔离。
  • /verify/code-review 停止自动运行主要是可预测性与控制权变化,不应直接称为漏洞修复。

10. 结论

Coding Agent 的风险不是“AI 会不会写错命令”,而是运行时会不会把一个无法证明安全的语义自动当成低风险。权限分析器必须像编译器一样解析、像 Policy Engine 一样决策、像 Sandbox 一样约束、像可观测系统一样审计。

最小安全不变量保持不变:

Unknown is not Safe.

来源

来源