api-key-hygiene-client-side · ZH · 2026-10-20

一把 key 散落在多台机器上:如何不让聚合站 key 进 git、shell 历史和前端打包

聚合站的无登录长期 key 虽然方便,但容易在 .env、shell 历史、前端打包和 CI 日志中泄漏。本文梳理这四个常见泄漏面,并给出用轮换习惯替代按人登录的具体做法,帮助你在享受一把 key 调多模型的同时,把风险控制在可接受范围内。

为什么无登录 key 的泄漏面更值得关注

聚合站通常不要求按人登录,而是签发一把长期有效的 API key。好处是接入简单,坏处是这把 key 一旦泄漏,攻击者不需要绕过账号体系就能直接消耗你的额度。没有登录会话、没有二次验证,泄漏即等于失守。因此,与其依赖“没人会拿到”,不如从工程习惯上减少 key 出现的场合。

下面按常见泄漏面逐一说明。

.env 与配置文件:最容易被提交的载体

把 key 放在 .env 里本身没问题,问题在于 .env 经常被误提交。

  • 项目初始化时就把 .env 加入 .gitignore,并提交一份 .env.example 只放占位符。
  • 用 git secrets、gitleaks 等工具在 pre-commit 阶段扫描疑似 key 的字符串。
  • 不要把 key 写进 docker-compose.yml、config.json 这类会被版本控制的文件;用环境变量注入。
  • 如果 key 已经进入 git 历史,仅删除文件不够,需要重写历史并立即轮换。

Shell 历史:一次 curl 就可能留下明文

调试时直接 curl -H "Authorization: Bearer sk-..." 很常见,这条命令会进入 ~/.bashhistory 或 ~/.zshhistory。

  • 调试时把 key 放进环境变量,命令里只引用变量名,例如 curl -H "Authorization: Bearer $API_KEY"。
  • 在命令前加空格并配置 HISTCONTROL=ignorespace(bash)或 setopt histignorespace(zsh),让带前缀的命令不写入历史。
  • 定期检查历史文件里是否有 sk- 开头的字符串,发现后清理并轮换。
  • 使用支持 secret 管理的 shell 插件或密码管理器注入,而不是手动 export 明文。

前端打包:key 一旦进 bundle 就是公开的

任何被打进前端 JavaScript 的 key 都等同于公开,因为浏览器端代码对用户完全可见。

  • 聚合站 key 只应出现在服务端或受控的构建环境中,不要放在 VITE、NEXTPUBLIC_ 这类会被注入前端的变量前缀下。
  • 前端需要调用模型时,走自己的后端代理,由后端持有 key 并做鉴权与限流。
  • 构建产物上线前用工具扫描 bundle 中是否出现疑似 key 的字符串。
  • 如果确实需要浏览器直连,考虑短期令牌方案,而不是长期 key。

CI 变量:日志和 fork PR 是两条泄漏路径

CI 里存放 key 看似安全,实际有两个常见出口:日志和不受信任的代码。

  • 把 key 存为 CI 的 secret 变量,不要写在 workflow 文件里。
  • 避免在 CI 脚本中 echo 或 set -x 打印包含 key 的命令;多数 CI 会对 secret 做掩码,但掩码不是万无一失。
  • 对来自 fork 的 PR 默认不注入 secret,防止恶意代码读取环境变量。
  • 限制 secret 的作用范围,按环境(开发、预发、生产)使用不同的 key。

用轮换习惯替代按人登录

无登录体系下,轮换是最实际的补偿控制。

  • 给不同用途签发不同的 key:本地开发、CI、生产服务各一把,泄漏时影响面可控。
  • 设定固定的轮换周期,例如按季度或按项目阶段更换;轮换后旧 key 及时吊销。
  • 在聚合站控制台为 key 设置可识别的备注名,便于定位是哪一把泄漏。
  • 记录 key 的签发时间和用途,避免出现“不知道这把 key 还用在哪”的情况。
  • 一旦怀疑泄漏,先吊销再排查,不要等到确认。

一个可落地的最小清单

  • .env 进 .gitignore,提交 .env.example。
  • pre-commit 扫描疑似 key。
  • shell 历史不记录含 key 的命令。
  • 前端不出现长期 key,统一走后端代理。
  • CI secret 按环境隔离,fork PR 不注入。
  • 按用途分 key,定期轮换,怀疑即吊销。

这些习惯不依赖登录体系,也不需要额外基础设施,但能显著降低长期 key 在常见工程流程中泄漏的概率。