9.1 权限模型设计
模型: claude-opus-4-6 (anthropic/claude-opus-4-6) 生成日期: 2026-02-17
AI Agent 能够执行 Shell 命令、修改文件、访问网络——这些能力在带来便利的同时也引入了巨大的安全风险。一个缺乏权限控制的 Agent 可能误删重要文件、泄露环境变量中的 API 密钥、或者执行危险的系统命令。权限控制系统是 OpenCode 安全架构的基石,它确保 Agent 的每一个敏感操作都在用户的知情和授权下进行。
本节将解析 OpenCode 权限系统的数据模型设计,包括三种权限动作、规则的定义结构、以及规则集的合并策略。
9.1.1 三种权限动作:allow、deny、ask
OpenCode 的权限系统基于三种基本动作(Action):
// permission/next.ts
export const Action = z.enum(["allow", "deny", "ask"])allow
允许
直接执行,不需要用户确认
deny
拒绝
直接阻止执行,抛出 DeniedError
ask
询问
暂停执行,弹出 TUI 对话框让用户决定
这三种动作构成了一个完整的决策空间:
allow是最宽松的——适用于低风险操作或用户已明确信任的操作(如读取项目内的文件)。deny是最严格的——适用于绝对不应该发生的操作(如 Agent 读取.env文件中的敏感信息)。ask是折中方案——也是默认行为。当没有任何规则明确匹配时,系统会回退到ask。
这种三值设计比简单的"允许/拒绝"二值模型更加灵活。ask 动作让用户在首次遇到某类操作时做出决定,并且可以选择"仅此一次"或"始终允许",从而在安全性和使用便捷性之间取得平衡。
9.1.2 PermissionNext.Rule:permission + pattern + action
权限规则(Rule)是权限系统的原子单位。每条规则由三个字段组成:
permission 字段标识了这条规则适用于哪种权限类型。OpenCode 中的每个工具在定义时都声明了自己需要的权限名称:
Bash
bash
命令执行权限
Edit / Write / Patch
edit
文件编辑权限
Read
read
文件读取权限
Glob
glob
文件查找权限
Grep
grep
内容搜索权限
Task
task
子 Agent 调度权限
Skill
skill
Skill 加载权限
WebFetch
webfetch
网页抓取权限
WebSearch
websearch
网页搜索权限
LSP
lsp
语言服务器权限
TodoWrite
todowrite
Todo 写入权限
TodoRead
todoread
Todo 读取权限
ExternalDirectory
external_directory
外部目录访问权限
CodeSearch
codesearch
代码搜索权限
—
doom_loop
循环检测权限(特殊)
pattern 字段是一个通配符模式,用于进一步限定规则的匹配范围。例如:
"*"—— 匹配所有模式(最宽泛)"ls *"—— 匹配ls开头的命令"/home/user/.env"—— 匹配特定文件路径"*.md"—— 匹配所有 Markdown 文件
action 字段指定当规则匹配时应该执行的动作。
一些具体的规则示例:
9.1.3 Ruleset:规则集合与合并策略
Ruleset 是 Rule 的有序数组:
从配置到 Ruleset 的转换
用户的权限配置通常以更简洁的格式书写(在 opencode.json 的 agent.permission 字段中)。fromConfig() 函数负责将这种简洁格式转换为标准的 Ruleset:
expand() 函数处理路径中的 ~ 和 $HOME 前缀,将它们展开为实际的 home 目录路径:
Ruleset 的合并策略
多个来源的 Ruleset 需要被合并为一个统一的规则集。OpenCode 的合并策略非常简洁:
合并就是简单的数组拼接。这意味着后面的规则会覆盖前面的规则——因为在评估时使用的是 findLast()(从后往前查找第一个匹配的规则)。这种"后来者优先"的设计让权限层级自然形成了一个 优先级链:
这种设计的优雅之处在于,它不需要复杂的优先级标记或权重计算——仅通过数组中的位置就决定了规则的优先级。我们将在 9.2 节中详细分析评估引擎的 findLast() 逻辑。
关于双系统共存
细心的读者可能注意到,OpenCode 源码中实际上有两个权限系统:
PermissionNext(permission/next.ts):新版权限系统,基于 Rule/Ruleset 模型。Permission(permission/index.ts):旧版权限系统,基于type+pattern模型。
两个系统目前共存于代码库中。PermissionNext 是更新、更完善的实现,它被 Session 系统和 Processor 主要使用。旧版 Permission 仍在部分代码路径中保留(如 Plugin 的 permission.ask 钩子),但正在逐步被 PermissionNext 取代。
本章主要分析 PermissionNext 的实现。两个系统的核心思路一致——基于"权限类型 + 匹配模式 → 动作"的规则模型。
本节小结
OpenCode 的权限系统基于三值动作模型(
allow/deny/ask),其中ask作为默认行为确保了安全优先的设计哲学。权限规则由permission(权限类型)、pattern(通配符模式)和action(动作)三个字段组成。多个来源的 Ruleset 通过简单的数组拼接合并,利用findLast()评估策略实现"后来者优先"的覆盖语义,使得权限层级自然形成优先级链。
Last updated
