Claude Code 权限分析器为什么必须 Fail Closed:v2.1.214 暴露的 5 类边界 + 6 类不能推出的结论

📅 2026/7/23 2:47:56 👁️ 阅读次数 📝 编程学习
Claude Code 权限分析器为什么必须 Fail Closed:v2.1.214 暴露的 5 类边界 + 6 类不能推出的结论

Claude Code 权限分析器为什么必须 Fail Closed(2026)

TL;DR

  • 场景:Claude Code v2.1.214(2026-07-18 01:20 UTC)在一个版本里集中修复了 7 类权限分析边界:路径 Glob 错误匹配、Windows PowerShell 5.1 Permission Check Bypass、Bash 文件描述符重定向解析差异、超长命令、zsh 条件表达式中的变量修饰符、help/man危险选项、远程 Daemon 参数、本地/远程 Session 审批时序;v2.1.215(2026-07-19 02:56 UTC)随后停止自动运行/verify/code-review,改为显式调用。
  • 结论:这些修复不能被简单概括为"加了几个黑名单"。Coding Agent 的权限系统面对的是编译器前端与 Policy Engine 的组合问题——原始字符串必须按目标 Shell 解析、规范化、识别副作用,再与规则和运行时隔离联合决策。最重要的安全不变量是:Unknown Syntax → Assume Harmless等于把解析器的不确定性转化为执行权限。
  • 产出:覆盖路径作用域 / Bash 重定向 / PowerShell 版本 / 远程 Daemon / 审批时序五类边界,Shell-Aware Parser + 副作用分类 + Policy Evaluation + Runtime Audit 四段式控制平面,Fail Closed 三层策略(可证明安全 / 不确定 / 明确高风险),Approval Fatigue 缓解与跨 Shell 回归测试矩阵,可作为 Coding Agent 权限系统设计与验收蓝本。

版本矩阵

功能状态说明
Claude Code v2.1.214 发布时间 2026-07-18 01:20 UTC,commit 07dcb0e✅ 已验证GitHub Releases 原文 + 网页 metadata 直接确认
修复单段dir/**规则(如Edit(src/**))自动批准项目树中任意位置同名dir/目录✅ 已验证GitHub Releases v2.1.214 原文第一条
修复 Windows PowerShell 5.1 会话下的 Permission Check Bypass✅ 已验证GitHub Releases v2.1.214 原文第二条
Bash 权限检查在 FD 重定向(分析器与 Bash 解析差异)上 Fail Closed✅ 已验证GitHub Releases v2.1.214 原文第三条
超过 10,000 字符的超长命令改为总是弹窗,不再自动运行✅ 已验证GitHub Releases v2.1.214 原文第四条
zsh[[ ]]条件中的变量下标与修饰符不再被当作惰性文本✅ 已验证GitHub Releases v2.1.214 原文第五条
help/man携带危险选项、命令替换、反斜杠路径时不再自动通过✅ 已验证GitHub Releases v2.1.214 原文第六条
Docker / Podmandockershim 携带--url/--connection/--identity/ Podman remote 时补齐权限提示✅ 已验证GitHub Releases v2.1.214 原文
远程 Session 权限请求不再在本地确认前提前执行✅ 已验证GitHub Releases v2.1.214 原文
OpenTelemetry 增加message.uuid/client_request_id/tool_source字段✅ 已验证GitHub Releases v2.1.214 原文
CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH配置 60KB 截断✅ 已验证GitHub Releases v2.1.214 原文
Claude Code v2.1.215 发布时间 2026-07-19 02:56 UTC,commit 015170d✅ 已验证GitHub Releases 原文
v2.1.215 停止自动运行/verify/code-review,需用户显式调用✅ 已验证GitHub Releases v2.1.215 原文
官方权限规则评估顺序Deny → Ask → Allow,第一条匹配规则决定结果✅ 已验证官方 Permissions 文档 S2
权限由 Claude Code 执行,不是由模型自行决定✅ 已验证官方 Permissions 文档 S2
Bash 执行可使用 OS 级文件系统和网络隔离✅ 已验证官方 Sandboxing 文档 S3
不存在对应 CVE 或公开 Security Advisory⚠️ 未公开GitHub Releases 只描述 fix,未配 CVE 编号

摘要

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. 官方权限模型给出的基础框架

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

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 的共同模型

命令审批和 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.

来源

  • [S1] Anthropic Claude Code GitHub Releases: https://github.com/anthropics/claude-code/releases
  • [S2] Claude Code Permissions: https://code.claude.com/docs/en/permissions
  • [S3] Claude Code Sandboxing: https://code.claude.com/docs/en/sandboxing
  • [S4] Claude Code Auto Mode Configuration: https://code.claude.com/docs/en/auto-mode-config
  • [S5] Claude Code Security: https://code.claude.com/docs/en/security

错误速查卡

症状根因定位修复
Edit(src/**)自动批准了项目树外任意dir/目录的写路径 Glob 解析时基准目录绑定错误,src/**被误匹配到任意位置同名目录跑单段dir/**规则 + 嵌套目录测试;看 v2.1.214 之前的版本行为升到 v2.1.214+;所有dir/**类规则改为<cwd>/dir/****/dir/**显式形式
Windows PowerShell 5.1 下whoami/Get-ChildItem等命令被静默放行PowerShell 5.1 与 7 的解析、编码、命令行为差异,5.1 下 Permission Check Bypass在 Win PS 5.1 跑权限敏感命令看是否提示升到 v2.1.214+;对 PS 5.1 单独跑权限测试;尽量升级到 PS 7
Bash FD 重定向如bash -c "cmd > /dev/null"解析不一致权限分析器与 Bash 对 FD 重定向的解析不同跑 FD 重定向变体测试;看 v2.1.214 changelog升到 v2.1.214+;Parser Differential 测两者 AST 是否等价;不等价时拒绝或 Ask
超长命令(10,000+ 字符)被自动放行旧版本在超长命令上误判为安全跑 10000+ 字符命令;看 v2.1.214 第 4 条升到 v2.1.214+;Pipeline 强制超长命令走 Ask
zsh[[ "$x" == ${y:-default} ]]被当作惰性文本权限分析器未识别 zsh[[ ]]中的变量下标与修饰符在 zsh 跑 zsh 特有条件;看 v2.1.214 第 5 条升到 v2.1.214+;为 zsh[[ ]]单建测试集
man -Phelp -s携带命令替换/反斜杠被静默放行旧规则把help/man默认安全,但其参数可触发子进程man -P "<cmd>"help <subcommand>测试;看 v2.1.214 第 6 条升到 v2.1.214+;对help/man强制走 Ask
docker --url=tcp://remote:2375 ps自动放行到远程 Daemon--url/--connection/--identity/ Podman remote 改写了目标执行域跑远程 Daemon 参数测试;看 v2.1.214 相关条目升到 v2.1.214+;对 docker / podman 携带 remote flag 强制 Ask 并要求人工确认 Endpoint
远程 Session 在本地确认前提前执行了命令远程 Session 与本地 Session 状态机不一致跑 Remote Session 权限请求时序测试;看 v2.1.214 相关条目升到 v2.1.214+;分布式状态机必须保证请求-展示-确认-执行-审计一致性
/verify//code-review在不需要时自动跑旧版本允许 Claude 自主决定调用 review 类 skill看 session 行为;查 v2.1.215 变更升到 v2.1.215+;这两个 skill 必须用户显式调用
只看命令字符串前缀就放行,实际语义不同权限分析器只做字符串前缀匹配,未做 Shell 解析跑同一前缀不同语义的命令对;看是否都被放行引入 Shell-Aware Parser + Parser Differential;不等价时拒绝或 Ask
审批弹窗只显示原始长字符串,用户连续点批准Approval Fatigue + 缺少语义摘要用户操作审计;Ask 节点统计审批界面展示 Action / Scope / Network / Credentials / Remote / Irreversible 等结构化字段
Parser 修复后直接当作 Sandboxing 替代两者解的是不同层问题,Analyzer 决定"是否允许尝试",Sandbox 决定"即使执行能触达什么"检查部署架构是否同时有 Analyzer + Sandbox两者必须叠加使用,不能互相替代
修改权限规则后没有重测 Analyzer 行为规则顺序、范围、路径基准变了,Analyzer 行为可能改变CI 上跑跨 Shell 回归测试矩阵把 8 维测试矩阵加入 CI,改动规则必须全绿
OpenTelemetry 字段不足以串联 Trace缺少message.uuid/client_request_id/tool_source检查 OTel 配置与字段映射升 v2.1.214+ 增加三字段;企业审计在此基础上加决策规则 ID、批准者、Exit Code、回滚状态
Prompt / CLAUDE.md / AGENTS.md 当作权限来用这些只能表达偏好,不能替代执行权限看权限是否在 Claude Code 执行层而非模型自决把权限决策收敛到 Claude Code 执行层,Prompt 层只表达行为偏好