API Key 不应该放在 shell 配置文件里
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,后果是:
- 每个终端会话启动就自动加载,任何子进程都能读到
env、printenv等命令随时能看到明文- AI 工具、日志收集、调试输出都可能意外捕获
- 一旦配置文件被同步到 dotfiles 仓库,直接公开
根本问题是:key 的生命周期远长于它实际被用到的时间。
更好的方式
方案一:项目级 .env + 精确注入
最轻量的改进。每个项目只放自己用到的 key,通过脚本精确提取,不污染全局环境。
my-project/
.env # 只含这个项目需要的 key,加入 .gitignore
run.sh # 精确读取 .env,只注入必要变量
scripts/
main.pyrun.sh 示例:
#!/bin/sh
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ENV_FILE="$SCRIPT_DIR/.env"
GHOST_HOST=$(grep '^GHOST_HOST=' "$ENV_FILE" | head -1 | cut -d= -f2-)
GHOST_ADMIN_API_KEY=$(grep '^GHOST_ADMIN_API_KEY=' "$ENV_FILE" | head -1 | cut -d= -f2-)
export GHOST_HOST GHOST_ADMIN_API_KEY
exec "$SCRIPT_DIR/.venv/bin/python" "$SCRIPT_DIR/scripts/main.py" "$@"优点:简单,无依赖,适用于所有操作系统。
缺点:key 仍然明文存在磁盘。
方案二:macOS Keychain
系统级加密存储。key 加密保存在 Keychain 里,只在被读取的瞬间解密到内存,cat、grep、env 全都看不到。
存入:
security add-generic-password -a "$USER" -s "MOONSHOT_API_KEY" -w "sk-your-key-here"在脚本里读取:
MOONSHOT_API_KEY=$(security find-generic-password -a "$USER" -s "MOONSHOT_API_KEY" -w)
export MOONSHOT_API_KEY使用体验: 开机登录 Mac 时系统 Keychain 自动解锁,整个会话期间脚本可以直接读取,不需要输密码。第一次访问某个条目时系统会弹一次授权框,点"始终允许"后就再也不会弹了。
这是替代 shell 配置文件存 key 的最直接方案,对工作流几乎没有影响。macOS 独有,Linux 和 Windows 有各自的等效方案(secret-tool、Windows Credential Manager)。
方案三:Bitwarden CLI(私有部署)
如果你有 Bitwarden 实例(包括私有部署的 Vaultwarden),可以用官方 CLI bw 在脚本里动态拉取 key。
配置私有部署地址:
bw config server https://your-bitwarden.example.com登录并获取 session:
bw login
export BW_SESSION=$(bw unlock --raw)Session 在当前终端会话内有效,关闭终端后失效,不会持久暴露。
在脚本里读取指定条目:
MOONSHOT_API_KEY=$(bw get password "Moonshot API Key")
export MOONSHOT_API_KEYbw get password 按条目名称检索,返回该条目的 password 字段。也可以用 bw get notes 获取备注字段,适合存储格式复杂的 key。
适合的场景: 多台设备共用同一套 key,或者需要跨平台(macOS/Linux/Windows 都支持)。key 集中在 Bitwarden 管理,换设备只需重新登录,不用手动迁移 .env 文件。
迁移建议
如果你现在 shell 配置文件里有大量 export KEY=xxx:
- 按项目整理,每个项目建一个
.env,只放该项目用到的 key - 高价值凭证(数据库密码、支付相关)迁移到 Keychain 或 Bitwarden
- 把 shell 配置文件里的
export KEY=全部删掉 - 确认
.env文件加入了.gitignore
不需要一次做完。先把最敏感的几个迁走,剩下的项目用到哪个迁哪个。
总结
| 方案 | 明文落盘 | 跨平台 | 跨设备 | 依赖 |
|---|---|---|---|---|
| shell 配置文件 | ✓(危险) | ✓ | 需手动同步 | 无 |
项目 .env |
✓ | ✓ | 需手动同步 | 无 |
| macOS Keychain | ✗ | ✗ | ✗ | 系统内置 |
| Bitwarden CLI | ✗ | ✓ | ✓ | bw CLI |
没有完美方案,但任何一个都比 shell 配置文件好。最实用的起点是:清空配置文件里的 key,改用项目级 .env,高价值凭证再逐步迁到 Keychain 或 Bitwarden。
Member discussion