随着 AI 编程助手在日常开发中的深度介入,安全问题变得愈发重要。一个能够随意读写文件、执行 Shell 命令、访问网络的 AI 工具,如果缺乏细粒度的权限控制,就可能成为安全隐患。OpenCode 从 v1.1.1 开始对权限系统进行了全面重构,将原来简单的 tools 开关升级为功能强大的 permission 配置体系,让开发者能够精确控制 Agent 的每一个操作。本文将系统讲解 OpenCode 权限管理的完整用法,帮助你构建既高效又安全的 AI 编程工作流。
在日常使用 AI 编程助手时,以下场景你可能并不陌生:
.env 文件内容并显示在终端中rm -rf 这样的危险命令这些场景的共同特征是:Agent 的操作范围超出了你的预期,而你缺少一种精细控制的能力。OpenCode 的权限系统正是为解决这些问题而设计的——它允许你对文件的读取和编辑、Shell 命令执行、网络访问、外部目录访问、子 Agent 调用等操作设置精确的"允许/询问/拒绝"规则。
OpenCode 中每条权限规则最终都会得出三种结果之一:
| 结果 | 含义 | 适用场景 |
|------|------|----------|
| allow | 无需确认,自动放行 | 信任的常规操作,如 git status |
| ask | 弹窗询问用户 | 需要人工判断的操作,如执行 curl 命令 |
| deny | 直接拒绝 | 危险操作或敏感文件访问 |
默认情况下,OpenCode 的策略比较宽松——大多数权限默认 allow,但有两个重要例外:doom_loop(死循环检测)和 external_directory(外部目录访问)默认为 ask。此外,.env 系列文件的读取也有特殊保护:
{
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
这意味着 Agent 默认不允许读取 .env、.env.production 等敏感文件,但允许读取 .env.example 这类模板文件。
最简单的配置方式是使用字符串简写,为整个工具类别设置统一策略:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"bash": "allow",
"edit": "deny"
}
}
上述配置的意思是:默认所有操作都需要询问(*: "ask"),唯独 Shell 命令自动放行(bash: "allow"),而所有文件编辑操作直接拒绝(edit: "deny")。这种配置适合"只读审查"场景——Agent 可以执行命令查看项目状态,但不能修改任何文件。
你还可以用一行设置全局策略:
{
"permission": "allow"
}
这会将所有权限设为 allow(但 .env 文件保护和 external_directory 等默认安全规则依然生效)。
简单的字符串模式只能做"全有或全无"的控制。实际开发中,我们往往需要对同一类操作进行分化管理——比如允许 git status,但拒绝 git push。OpenCode 的对象语法完美支持这种需求。
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git status *": "allow",
"git diff *": "allow",
"git log *": "allow",
"git branch *": "allow",
"grep *": "allow",
"npm test *": "allow",
"npm run dev *": "allow",
"npm run build *": "allow",
"git push *": "deny",
"git commit *": "ask",
"rm -rf *": "deny",
"rm -r *": "deny",
"curl *": "ask",
"wget *": "ask"
}
}
}
规则匹配遵循"最后匹配获胜"原则。通常将 * 通配规则放在前面,后面跟具体的覆盖规则。上面的配置实现了:
注意模式末尾的 *:"git status *" 可以匹配 git status、git status --short、git status --porcelain 等任何带后缀的命令。
{
"edit": {
"*": "ask",
"*.md": "allow",
"packages/web/src/**/*.tsx": "allow",
"package.json": "ask",
"*.lock": "deny",
".github/workflows/*.yml": "deny"
}
}
这个配置的策略很清晰:允许编辑文档和前端组件,修改 package.json 需要确认,锁文件和 CI 配置文件禁止修改,其余文件默认询问。
{
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow",
"*.pem": "deny",
"*.key": "deny",
"*.p12": "deny",
"*.pfx": "deny",
"*credentials*": "deny",
"*secret*": "deny",
".git/config": "deny",
"**/secrets/**": "deny",
"**/private/**": "deny"
}
}
这个配置加了一层敏感的"安全防线":除了默认的 .env 保护外,还禁止读取私钥文件(.pem、.key)、证书文件(.p12、.pfx)、凭证文件,以及 secrets/ 和 private/ 目录下的所有内容。
OpenCode 支持以下权限键:
| 权限键 | 控制范围 | 支持精细控制 |
|--------|----------|:--:|
| read | 文件读取 | 是 |
| edit | 文件编辑(涵盖 write、edit、patch) | 是 |
| glob | 文件匹配搜索 | 是 |
| grep | 内容搜索 | 是 |
| bash | Shell 命令执行 | 是 |
| task | 子 Agent 调用 | 是 |
| skill | 技能加载 | 是 |
| lsp | LSP 查询 | 否 |
| question | Agent 提问 | 否 |
| webfetch | 网页抓取 | 是 |
| websearch | 网页搜索 | 是 |
| external_directory | 外部目录访问 | 是 |
| doom_loop | 死循环检测 | 否 |
其中 external_directory 是一个特殊的安全守卫——当 Agent 尝试访问工作目录之外的文件时触发,相当于一道"边界防线"。
OpenCode 允许为不同 Agent 设置不同权限,这在多 Agent 协作时尤为重要。
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"grep *": "allow"
},
"edit": "ask"
},
"agent": {
"build": {
"mode": "primary",
"permission": {
"bash": {
"*": "allow",
"git push *": "deny",
"rm *": "deny"
},
"edit": "allow"
}
},
"plan": {
"mode": "primary",
"permission": {
"edit": "deny",
"bash": "deny"
}
},
"code-reviewer": {
"description": "代码审查专用 Agent",
"mode": "subagent",
"temperature": 0.1,
"permission": {
"edit": "deny",
"bash": {
"*": "deny",
"grep *": "allow",
"git diff *": "allow",
"git log *": "allow"
},
"webfetch": "deny"
}
}
}
}
在这个配置中:
git push 和 rm 系列命令Agent 级别的配置会与全局配置合并,Agent 配置的优先级更高。这意味着在全局设置了 edit: "ask",但在 build Agent 中设置了 edit: "allow",那么 build Agent 的文件编辑将自动放行。
对于以 .md 文件定义的 Agent,权限可以直接写在 frontmatter 中:
---
description: 安全审查专用 Agent
mode: subagent
temperature: 0
permission:
edit: deny
bash:
"*": deny
"grep *": allow
"git diff *": allow
"git log *": allow
webfetch: deny
---
你是一个安全审查 Agent。你的任务是检查代码中的安全隐患。
规则:
1. 绝不输出实际的密钥、token 或密码内容
2. 发现问题时引用文件和行号,不展示敏感值
3. 建议使用环境变量、密钥管理器等安全方案
4. 关注硬编码凭证、不安全的配置、敏感信息泄露
你还可以控制哪个 Agent 可以调用哪些子 Agent:
{
"agent": {
"orchestrator": {
"mode": "primary",
"permission": {
"task": {
"*": "deny",
"code-reviewer": "allow",
"test-runner": "allow"
}
}
}
}
}
当 task 权限设为 deny 时,对应的子 Agent 会从 Task 工具的描述中完全移除,模型甚至不会尝试调用它。
external_directory 是 OpenCode 的一道重要安全防线。当 Agent 需要访问项目工作目录之外的文件时,必须先过这一关:
{
"permission": {
"external_directory": {
"~/.ssh": "deny",
"~/.gnupg": "deny",
"/etc/*": "deny",
"/var/*": "deny",
"/tmp/*": "allow",
"*": "ask"
}
}
}
这个配置明确拒绝了 SSH 密钥和 GPG 密钥目录的访问,系统敏感目录也被阻挡在外,/tmp 目录可用作临时共享空间,其他外部路径则会触发询问。
你还可以为外部目录中的文件设置更精细的操作限制:
{
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
},
"edit": {
"~/projects/personal/**": "deny"
}
}
}
这样 Agent 可以读取个人项目中的文件作为参考,但不能修改它们。
以下是一份适合大多数项目的综合安全配置:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow",
"*.pem": "deny",
"*.key": "deny",
"*.p12": "deny",
"*.pfx": "deny",
"*credentials*": "deny",
"*secret*": "deny",
".git/config": "deny",
"**/secrets/**": "deny",
"**/private/**": "deny"
},
"edit": {
"*": "allow",
"*.lock": "deny",
"package-lock.json": "deny",
"yarn.lock": "deny",
"pnpm-lock.yaml": "deny",
"Cargo.lock": "deny",
".github/workflows/*.yml": "ask"
},
"bash": {
"*": "ask",
"git status *": "allow",
"git diff *": "allow",
"git log *": "allow",
"git branch *": "allow",
"grep *": "allow",
"npm test *": "allow",
"npm run lint *": "allow",
"npm run typecheck *": "allow",
"npm run build *": "allow",
"git push *": "deny",
"git push --force *": "deny",
"rm -rf *": "deny",
"rm -r *": "deny",
"curl *": "ask",
"wget *": "ask",
"printenv *": "deny",
"env": "deny",
"export *": "deny"
},
"webfetch": "ask",
"websearch": "ask",
"external_directory": {
"~/.ssh": "deny",
"~/.gnupg": "deny",
"/etc/*": "deny",
"/tmp/*": "allow",
"*": "ask"
},
"doom_loop": "ask"
},
"agent": {
"plan": {
"permission": {
"edit": "deny",
"bash": {
"*": "deny",
"grep *": "allow",
"git diff *": "allow"
},
"webfetch": "deny"
}
},
"code-reviewer": {
"description": "代码审查 Agent — 只读",
"mode": "subagent",
"permission": {
"edit": "deny",
"bash": {
"*": "deny",
"grep *": "allow",
"git diff *": "allow",
"git log *": "allow"
},
"webfetch": "deny",
"websearch": "deny"
}
}
}
}
这个配置的设计思路:
严防密钥泄露:所有凭证类文件禁止读取和编辑
保护锁文件:lock 文件禁止自动修改,防止意外的依赖变更
白名单命令策略:Safe 的 Git 只读命令和开发命令自动放行,危险命令拒绝
网络操作需确认:webfetch 和 websearch 设为 ask,防止数据泄露
外部目录隔离:SSH 密钥和系统目录彻底拒绝,临时目录放开
Agent 分工明确:plan Agent 只能阅读思考,code-reviewer 只能审查分析
从 OpenCode v1.1.1 起,TUI 内置了权限管理对话框。打开命令面板(Ctrl+P),选择"Permissions"即可查看和管理当前的所有权限规则。对话框展示四个层级的权限:
Session(会话级):通过 always 授权临时添加的规则,重启后失效
Project(项目级):当前项目 opencode.json 中的配置
Global(全局级):~/.config/opencode/opencode.json 中的配置
Default(默认):Agent 的内置默认规则
这四个层级按 1 > 2 > 3 > 4 的优先级进行覆盖合并。你可以在对话框中直接增删改规则,修改会持久化到对应的配置文件。
当一条 ask 规则被触发时,OpenCode 会在 TUI 中弹出审批对话框,提供三种选择:
| 选择 | 效果 |
|------|------|
| once | 仅本次放行 |
| always | 当前会话内始终放行(添加临时 allow 规则) |
| reject | 拒绝此次操作 |
其中 always 是一个很实用的功能——当你信任某个模式时,选择 always 会在会话内自动添加一条 allow 规则,后续相同模式的请求会直接通过,无需反复确认。不过这条临时规则不会持久化到磁盘,重启后即失效,这是一种有意的安全设计。
--auto 命令行参数也会影响审批行为:使用 opencode --auto 启动时,所有 ask 请求会被自动以 once 方式回复。但配置中明确的 deny 规则仍然生效,不会被绕过。
OpenCode 的权限管理系统是一套从简单到复杂、从全局到 Agent 逐层递进的精细控制体系。核心要点回顾:
allow(放行)、ask(询问)、deny(拒绝).env 文件默认拒绝读取,external_directory 和 doom_loop 默认询问合理的权限配置不是要阻碍开发效率,而是为 AI 编程助手划定一个"安全活动范围"——让它在信任的区域内自由发挥,在敏感边界上主动询问,在危险地带直接止步。结合 AGENTS.md 中的安全规则声明和多 Agent 分工协作,你可以构建出一个既高效又安全的 AI 编程环境。建议从偏保守的配置开始,根据实际使用体验逐步放宽策略,找到安全与效率的最佳平衡点。