# 权限与安全：让 AI 有破坏力但不失控


<!-- more -->


给 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` 命令可以切换到只读规划模式。

这种动态切换的设计意图很明确：**不同的任务阶段需要不同的信任级别。**

一个典型的工作流可能是：
1. 启动时 `plan` 模式——让 Agent 先分析项目，只读不写
2. 分析完成后切到 `default`——开始改代码，关键操作确认
3. 大规模重构时切到 `acceptEdits`——信任 Agent 的编辑能力，减少确认疲劳
4. 涉及外部操作时切回 `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](https://github.com/ByronFinn/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 官方源码](https://github.com/anthropics/claude-code)项目进行架构分析，聚焦设计思想而非代码实现。

