权限与安全:让 AI 有破坏力但不失控
给 AI 编程助手文件写入权限,相当于把剪刀递给一个非常聪明但偶尔会幻视的人。
它大多数时候知道自己在干什么,但偶尔会自信满满地删掉一个不该删的文件,或者把一个关键的配置改成看起来合理但实际错误的值。模型不是恶意的,它只是会犯错——而且犯错时通常很自信。
Claude Code 的权限系统要解决的就是这个问题:在"每次都问太烦"和"不问太危险"之间找到平衡点。
三轴分类:操作的风险矩阵
Claude Code 的权限系统首先对工具调用做了一个三轴分类:
Read(读取)——read_file、grep、glob、ls。这类操作不改变任何状态,最坏结果是浪费了一点 token。默认放行。
Edit(编辑)——write_file、edit、bash(有副作用的命令)。这类操作改变项目文件,可能引入错误,但通常可回滚(Git)。分级处理。
External(外部)——web_search、web_fetch、bash(网络请求)。这类操作触达项目之外的系统,可能产生不可逆的副作用(发请求、调 API)。最谨慎处理。
三轴不是绝对的。bash 命令横跨所有三轴——ls是 Read,rm -rf是 Edit,curl -X POST是 External。权限系统需要解析命令内容来判断风险等级,这本身就有一定不确定性。
5 级权限模型
Claude Code 定义了 5 个权限级别,从最宽松到最严格:
default——中间态。Read 直接执行,Edit 视情况确认,External 默认确认。这是大多数人的日常使用模式。
plan——只读模式。所有 Write 和 External 操作被禁止,Agent 只能读取和分析。适合"让我先了解一下这个项目"的场景。
acceptEdits——信任编辑。Read 和 Edit 直接执行,只有 External 需要确认。适合"你帮我改代码吧,我信你"的场景。
bypassPermissions——完全信任。所有操作无需确认。适合高度信任的场景或自动化流水线。不建议日常使用。
dontAsk——完全不信任。所有操作都需要确认。等同于手动审核每一步。适合学习调试或极端敏感的项目。
这 5 个级别不是"安全等级",而是信任校准旋钮。用户根据当前任务的敏感度和对 Agent 的信任度,手动调节。
信任不应该是二元的
大多数工具的权限模型是二元的:有权限或没权限。文件系统是读写执行位,API 是 OAuth scope,Docker 是 root 或不是。
Claude Code 的权限模型是连续的。它承认信任不是一个开关而是一个滑块——你对 Agent 的信任程度取决于上下文:
- 你在改一个测试文件 vs. 改生产部署配置 → 信任度不同
- Agent 已经在这个项目上工作了 10 轮 vs. 刚启动第 1 轮 → 信任度不同
- 你是这个项目的作者 vs. 你刚 clone 下来 → 信任度不同
5 级权限模型是对这种"上下文信任"的粗略近似。它不够精细(理想情况下应该是每个操作动态评估),但它在可用性和安全性之间找到了一个人类可以理解的平衡点。
确认机制的设计细节
当 Agent 发起一个需要确认的操作时,权限系统会暂停循环,向用户展示一个确认请求。这个请求不是简单的"确认/取消",它包含结构化信息:
- 什么工具被调用
- 什么参数被传入
- 为什么Agent 认为需要这个操作(基于之前的对话上下文)
用户基于这些信息做判断。这不是"盲信任",而是知情决策。
确认机制还有一个细节:连续确认的疲劳管理。如果 Agent 在短时间内容发起大量需要确认的操作(比如批量修改 20 个文件),用户会陷入"确认疲劳"——不停地点"确认"而不真正阅读内容。Claude Code 的应对策略是允许用户切换到更宽松的权限模式,或者使用 acceptEdits 模式批量信任编辑操作。
这揭示了一个深层矛盾:安全性便利性的零和博弈。越安全越麻烦,越方便越危险。权限系统的本质是在这个光谱上找一个让用户舒服的锚点。
权限模式的切换
权限模式不是固定的。用户可以通过命令在运行时切换——/permissions 命令可以调整当前会话的权限级别,/plan 命令可以切换到只读规划模式。
这种动态切换的设计意图很明确:不同的任务阶段需要不同的信任级别。
一个典型的工作流可能是:
- 启动时
plan模式——让 Agent 先分析项目,只读不写 - 分析完成后切到
default——开始改代码,关键操作确认 - 大规模重构时切到
acceptEdits——信任 Agent 的编辑能力,减少确认疲劳 - 涉及外部操作时切回
default或dontAsk——谨慎处理网络请求
权限模式切换不是安全功能,它是工作流功能。它让用户在不同的任务阶段调整与 Agent 的协作粒度。
安全不是权限系统一件事
权限系统是 Claude Code 安全架构的一环,但不是全部。其他安全措施包括:
System Prompt 约束。 前面聊过,system prompt 里有明确的行为规则:“最小变更原则"“先理解再行动"“不要编造文件内容”。这些是软约束,靠模型的理解力执行,不靠强制力。
工具级别的防护。 某些工具有内置的安全检查。比如 bash 工具会拒绝明显危险的命令模式(如不带确认的 rm -rf /),write_file 会拒绝写入项目目录之外的路径。
Git 作为安全网。 Claude Code 深度集成 Git——所有文件变更都可以在 Git 历史中追踪和回滚。权限系统防止错误发生,Git 系统在错误发生后提供恢复手段。
会话日志。 所有工具调用和模型输出都被记录。出了问题可以回溯完整的事件链。
安全不是单一机制,是纵深防御(Defense in Depth)。权限系统是其中一层,和 system prompt 约束、工具级防护、Git 回滚、会话日志一起构成多层防护。
延伸阅读:BYF 的 Approval 系统与生命周期 Hooks
BYF 的权限系统在 Claude Code 的 5 级权限模型基础上,增加了两个值得关注的设计:
1. 审批(Approval)作为独立子系统。 BYF 的 Approval 层不只是"同意/拒绝”,它是一个完整的权限门控管道。工具执行前,代理向用户展示结构化信息(命令、diff、文件操作详情),用户选择批准、拒绝或取消。审批结果通过 blockedReason 字段流回工具结果——不是简单的"是否执行”,而是"为什么没执行"(被拒绝 vs. 被取消),让模型能根据具体原因调整行为。
2. 生命周期 Hooks。 BYF 允许用户在工具调用的关键节点挂载本地命令——pre-tool(执行前审计)、post-tool(执行后通知)。这意味着用户可以用 shell 脚本实现自己的安全策略:比如"每次写文件前检查是否涉及生产配置目录"或"每次执行后弹个桌面通知"。BYF 不替你定义安全规则,它给你一个钩子机制让你自己定义。
这两个设计指向同一个方向:信任不是权限模型的预设值,而是用户在交互中动态构建的。 BYF 的 hooks 系统尤其有趣——它让用户在不修改 BYF 核心代码的前提下,将自己的安全策略嵌入 Agent 的执行流。
权限系统的哲学
Claude Code 的权限系统背后有一条设计哲学:
AI Agent 不应该被完全信任,也不应该被完全不信任。它应该被"有边界地信任"——在明确的边界内自主行动,在边界上请求确认,在边界外被禁止。
这条哲学和传统软件的"最小权限原则"(Principle of Least Privilege)一脉相承,但有一个关键差异:传统软件的最小权限是静态的(进程启动时授予固定权限),AI Agent 的最小权限是动态的(根据任务阶段、用户偏好、操作类型实时调整)。
动态最小权限是一个更年轻、更不成熟的设计领域。Claude Code 的 5 级模型是一个起点,不是终点。未来的方向可能是更细粒度的自动风险评估——不需要用户手动调旋钮,系统根据操作类型、项目敏感度、Agent 置信度自动计算"这次操作该不该问"。
但在那之前,5 级旋钮是一个合理的工程妥协。它不完美,但它让用户有控制权,让 Agent 有行动空间。
下一篇
Phase 1 的四篇文章完成了 Think-Act-Observe 循环、工具系统、System Prompt、权限安全——这是 AI Agent 的核心骨架。
Phase 2 进入更深层的能力。下一篇文章要聊的是上下文压缩——当对话越来越长、工具调用越来越多,上下文窗口迟早不够用。Claude Code 用四层管道让 AI 看起来拥有"无限记忆",但这背后是一场精密的 token 管理游戏。
本系列基于 Claude Code 官方源码项目进行架构分析,聚焦设计思想而非代码实现。