OpenCode 权限规则完全指南:用精细化权限管控让 AI 编程助手安全可控

OpenCode 权限规则完全指南:用精细化权限管控让 AI 编程助手安全可控

引言

随着 AI 编程助手在日常开发中的深度使用,安全问题逐渐浮出水面。当你允许 AI 执行终端命令、读写文件、甚至操作 Git 仓库时,如何确保它不会误删数据库、覆盖配置文件、或者执行有副作用的命令?OpenCode 的 Permission Rules(权限规则)系统正是为此而生。本文将从基础概念到实战配置,带你全面掌握这套权限管控体系。

理解 Permission Rules 与 Policies 的区别

在开始配置之前,有必要先厘清两个容易混淆的概念:

  • Policies(策略):控制的是 LLM 提供商的访问权限——哪些模型可以使用、哪些不能。属于"谁来思考"的层面。
  • Permission Rules(权限规则):控制的是 AI 能够执行的操作——允许执行哪些命令、读写哪些文件、访问哪些工具。属于"能做什么"的层面。

两者共同构成了 OpenCode 的安全防线,但本文聚焦后者。

三种权限模式

Permission Rules 为每一项操作定义了三种模式:

  • allow:自动允许,静默执行。适用于安全、无副作用的操作,如读取日志、查看文件状态。
  • ask:询问用户,等待确认。适用于有潜在风险的操作,如删除文件、执行数据库迁移。
  • deny:拒绝执行,直接拦截。适用于高危操作,如生产环境的数据删除、系统配置修改。

基础配置:在 opencode.json 中定义权限规则

Permission Rules 的配置位于项目根目录的 opencode.json 文件中,通过 permissionRules 字段定义:

{
  "permissionRules": [
    {
      "name": "safe-read-operations",
      "match": {
        "kind": "read",
        "path": ["/path/to/project/**"]
      },
      "mode": "allow"
    },
    {
      "name": "ask-before-write",
      "match": {
        "kind": "write",
        "path": ["/path/to/project/app/**", "/path/to/project/resources/**"]
      },
      "mode": "ask"
    },
    {
      "name": "deny-sensitive-commands",
      "match": {
        "kind": "command",
        "commandPrefix": ["rm -rf", "drop table", "truncate"]
      },
      "mode": "deny"
    }
  ]
}

匹配规则详解

每条规则通过 match 字段定义匹配条件,支持以下维度:

  • kind:操作类型,支持 readwritecommandedit 等。
  • path:文件路径 glob 模式,用于匹配文件读写操作。
  • commandPrefix:命令前缀匹配,用于控制终端命令。
  • tool:工具名称匹配,用于控制自定义工具调用。

实战场景:为 Laravel 项目配置权限规则

以本项目(Laravel 应用)为例,一套实用的权限规则配置如下:

{
  "permissionRules": [
    {
      "name": "auto-allow-composer-read",
      "match": {
        "kind": "read",
        "path": ["**/composer.json", "**/composer.lock"]
      },
      "mode": "allow"
    },
    {
      "name": "ask-migrations",
      "match": {
        "kind": "command",
        "commandPrefix": ["php artisan migrate"]
      },
      "mode": "ask"
    },
    {
      "name": "deny-prod-commands",
      "match": {
        "kind": "command",
        "commandPrefix": [
          "php artisan db:wipe",
          "php artisan migrate:fresh --seed",
          "rm -rf storage"
        ]
      },
      "mode": "deny"
    },
    {
      "name": "allow-safe-commands",
      "match": {
        "kind": "command",
        "commandPrefix": [
          "php artisan route:list",
          "php artisan cache:clear",
          "composer install --dry-run",
          "npm run build"
        ]
      },
      "mode": "allow"
    }
  ]
}

权限规则的优先级与合并

当多条规则匹配同一个操作时,OpenCode 按照以下优先级裁决:

deny 优先级最高——只要有一条规则判定 deny,操作即被拦截

ask 次之——没有 deny 规则时,任何一条 ask 规则都会触发询问

allow 优先级最低——仅在没有任何 deny 或 ask 规则匹配时生效

利用这个优先级机制,你可以先写一条宽泛的 deny 规则作为安全底线,再逐条添加 allow 例外:

{
  "permissionRules": [
    {
      "name": "deny-all-writes",
      "match": { "kind": "write", "path": ["**"] },
      "mode": "deny"
    },
    {
      "name": "allow-app-writes",
      "match": { "kind": "write", "path": ["/project/app/**"] },
      "mode": "allow"
    },
    {
      "name": "ask-config-changes",
      "match": { "kind": "write", "path": ["/project/config/**"] },
      "mode": "ask"
    }
  ]
}

在这个例子中,deny-all-writes 拦截所有写操作,allow-app-writes 对 app 目录开放写入权限,而 config 目录的修改需要用户确认。这就是"最小权限原则"在 AI 编程助手上的具体实践。

调试权限规则

OpenCode 提供了 --verbose 标志,可以在运行过程中输出详细的权限判断信息,帮助你排查规则配置问题:

opencode --verbose

输出中会包含类似以下内容的日志行:

[permission:allow] read /project/app/Models/User.php matched by "safe-read-operations"
[permission:ask]  write /project/config/app.php matched by "ask-config-changes"
[permission:deny] command "rm -rf /" matched by "deny-sensitive-commands"

最佳实践总结

从严格开始:先用 deny 覆盖所有操作,再逐个开放需要的权限。

命令前缀要具体php artisanphp 更精确,php artisan migrate 又比 php artisan 更安全。

善用 ask 模式:对于无法自动裁决的操作,让用户做最终决定,而不是直接允许或拒绝。

定期审查规则:随着项目演进,及时清理过时规则,补充新的安全约束。

结合环境变量:通过环境变量区分开发/生产环境,在不同环境加载不同的权限规则。

结语

Permission Rules 是 OpenCode 安全体系中最贴近开发者的防线。通过精心配置,你可以在享受 AI 编程助手带来的效率提升的同时,将安全风险降到最低。从今天开始,为你的项目制定一套专属的权限规则吧——毕竟,AI 越强大,越需要明确的边界。这套规则不仅保护了你的代码资产,也让 AI 助手在你的管控之下发挥出最大的生产力。