API Key 不应该放在 shell 配置文件里

把 API Key 写在 .bashrc / .zshrc 里风险被长期低估。本文梳理更安全的密钥存储方案与迁移路径。

API Key 不应该放在 shell 配置文件里。这是很多开发者都有的习惯,图省事,但风险被长期低估。

最近一次操作失误让我意识到这个问题:一条命令找不到目标文件,fallback 执行了 env,把整个终端环境变量打印出来,十几个 API key 直接进了 AI 对话的上下文,不得不全部轮替。

事故很小,但揭示了一个结构性问题:把 key 放在 shell 配置文件里,意味着它们始终暴露在所有子进程、所有工具的视野里。

为什么 shell 配置文件不适合存 API key

不同的 shell 有不同的配置文件,但都面临同样的问题:

  • zsh~/.zshrc~/.zprofile
  • bash~/.bashrc~/.bash_profile~/.profile
  • fish~/.config/fish/config.fish

在这些文件里写 export API_KEY=xxx,后果是:

  • 每个终端会话启动就自动加载,任何子进程都能读到
  • envprintenv 等命令随时能看到明文
  • AI 工具、日志收集、调试输出都可能意外捕获
  • 一旦配置文件被同步到 dotfiles 仓库,直接公开

根本问题是:key 的生命周期远长于它实际被用到的时间

更好的方式

方案一:项目级 .env + 精确注入

最轻量的改进。每个项目只放自己用到的 key,通过脚本精确提取,不污染全局环境。

run.sh 示例:

优点:简单,无依赖,适用于所有操作系统。

缺点:key 仍然明文存在磁盘。

方案二:macOS Keychain

系统级加密存储。key 加密保存在 Keychain 里,只在被读取的瞬间解密到内存,catgrepenv 全都看不到。

存入:

在脚本里读取:

使用体验: 开机登录 Mac 时系统 Keychain 自动解锁,整个会话期间脚本可以直接读取,不需要输密码。第一次访问某个条目时系统会弹一次授权框,点"始终允许"后就再也不会弹了。

这是替代 shell 配置文件存 key 的最直接方案,对工作流几乎没有影响。macOS 独有,Linux 和 Windows 有各自的等效方案(secret-tool、Windows Credential Manager)。

方案三:Bitwarden CLI(私有部署)

如果你有 Bitwarden 实例(包括私有部署的 Vaultwarden),可以用官方 CLI bw 在脚本里动态拉取 key。

配置私有部署地址:

登录并获取 session:

Session 在当前终端会话内有效,关闭终端后失效,不会持久暴露。

在脚本里读取指定条目:

bw get password 按条目名称检索,返回该条目的 password 字段。也可以用 bw get notes 获取备注字段,适合存储格式复杂的 key。

适合的场景: 多台设备共用同一套 key,或者需要跨平台(macOS/Linux/Windows 都支持)。key 集中在 Bitwarden 管理,换设备只需重新登录,不用手动迁移 .env 文件。

迁移建议

如果你现在 shell 配置文件里有大量 export KEY=xxx

  1. 按项目整理,每个项目建一个 .env,只放该项目用到的 key
  2. 高价值凭证(数据库密码、支付相关)迁移到 Keychain 或 Bitwarden
  3. 把 shell 配置文件里的 export KEY= 全部删掉
  4. 确认 .env 文件加入了 .gitignore

不需要一次做完。先把最敏感的几个迁走,剩下的项目用到哪个迁哪个。

总结

方案 明文落盘 跨平台 跨设备 依赖
shell 配置文件 ✓(危险) 需手动同步
项目 .env 需手动同步
macOS Keychain 系统内置
Bitwarden CLI bw CLI

没有完美方案,但任何一个都比 shell 配置文件好。最实用的起点是:**清空配置文件里的 key,改用项目级 ****.env**,高价值凭证再逐步迁到 Keychain 或 Bitwarden。