给每个 AI agent 单独发一张令牌:30 分钟配完,附验收命令

2026-09-24 工程实践凭据安全AI agent可复制

Supabase 的作用域令牌今天进了 public alpha 并逐步放量,把一件本来就该做的事变成了可以马上执行的事:交给机器的令牌,只给它需要的那一扇门。

一人公司在这件事上的处境比大公司更危险。大公司有专门的平台组管密钥,你一个人要同时维护 CI、定时任务、MCP server、n8n 流程,还有本地跑的各种脚本。省事的做法是生成一把令牌到处用,而到处用的令牌通常就是全权限的那把。

第一步:先摸清令牌在哪

grep -rInE "(sbp_[a-f0-9]|sbp_[A-Za-z0-9]|ghp_|github_pat_|sk-[A-Za-z0-9]{20}|CLOUDFLARE_API_TOKEN=)" \
  --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=dist .

命中的地方通常比想象中多。除了代码,重点看这几处:

  • MCP 配置(~/.cursor/mcp.json、claude_desktop_config.json)——AI agent 用的令牌几乎都藏在这
  • CI 的 secrets 里那些两年前加的、名字叫 SUPABASE_TOKEN 的变量
  • .env 和 .env.local,尤其是没进 .gitignore 的那些
  • docker-compose.yml 里的 environment

把命中的每一行记下来,包括”这个令牌被用在哪”。这一步的产物不是列表,是下面这张台账的草稿。

第二步:按用途拆开

原则是一个用途一张,绝不复用。三家常客的具体做法:

Supabase(作用域令牌,前缀 sbp_fc) 在 access tokens 设置页创建,创建时勾组织和项目,再勾权限。文档里的权限对照表标了每个 Management API 端点和每个 MCP 工具分别需要哪个权限,照着勾。给 MCP agent 的那张通常只需要:Database 读、Logs 读。

GitHub(fine-grained personal access token,前缀 github_pat_) 在 Settings → Developer settings → Personal access tokens → Fine-grained 创建。选单个仓库、勾最小权限(比如只给 Contents 读 + Issues 写)。它的好处是能设 90 天强制到期,classic 令牌做不到。

Cloudflare(API token) 在 dashboard 的 My Profile → API Tokens 用”Create Custom Token”,按账号/区域/具体服务缩小范围。给部署用的那张只需要某个 Pages 项目的编辑权限,不要给整账号。

拆完之后,本地和 CI 里都改成从环境变量读:

export SUPABASE_AGENT_TOKEN="sbp_fc_..."   # 只读,给 agent
export SUPABASE_DEPLOY_TOKEN="sbp_fc_..."  # 可写,只给 CI

第三步:建一张台账

不用上工具,一个 credentials.md(放在仓库外,比如密钥管理器里)就够:

用途前缀权限范围放在哪创建日到期/轮换日
MCP agent 读库sbp_fc项目 A:Database 读、Logs 读本地 env2026-09-242026-12-24
CI 部署sbp_fc项目 A:Database 写、Edge Functions 写GitHub Secrets2026-09-242026-12-24

令牌名字本身也带上信息:agent-readonly-projA-2026Q4。半年后你看到这个名字,不用查表就知道它能干什么、该不该还在。

验收标准

  1. 越权必须 403。 拿每张令牌去调一个它不该碰的端点,比如用只读令牌写库:

    curl -i "https://api.supabase.com/v1/projects/$PROJECT_REF/types/typescript" \
      -H "Authorization: Bearer $SUPABASE_AGENT_TOKEN"

    期望 HTTP 403。返回 200 说明勾多了,重开一张。

  2. 抽掉任意一张,只挂一个任务。 把 SUPABASE_AGENT_TOKEN 从环境里删掉,跑一遍全部自动化:应该只有一个流程报错,而且报错信息里带着这个变量名。如果挂了三四个,说明还在复用。

  3. 仓库里零明文。 第一步那条 grep 跑完只有零命中。CI 走 secrets,本地走密钥管理器或不起眼的 ~/.config/xxx/env。

  4. 轮换不用改代码。 换令牌时 git status 是干净的——改的只有环境变量和台账那一行。

第 2 条最容易被跳过,也最说明问题:它测的不是权限配得对不对,是你到底有没有真的拆开。

维护成本

一个季度 15 分钟,建议挂在每季度最后一周:跑一遍 grep,按台账逐个轮换,顺手删掉那些”已经想不起来是给谁用的”令牌——它们的存在本身就是风险。

顺带一句:这套做法对模型 API key 一样适用。给自动化的那把 key 单独开一个项目、单独设消费上限,跟给 agent 单独发令牌是同一件事——让每一份权限都能被单独撤销。