今天刷掘金热榜,看到那篇 VS Code 插件供应链攻击的文章直接给我整不会了——两个"浓眉大眼"的 AI 编程插件,150 万安装量,背地里偷代码、偷 API Key、偷 SSH 密钥,偷得明明白白。
我当时的反应:
卧槽,我自己的 key 是不是也在裸奔?
然后我花了一个下午,把自己电脑上所有跟 AI 相关的 key 全翻了一遍。
结论:比我想象的严重 10 倍。
先说说我的"案发现场"
我是独立开发者,平时写代码重度依赖各种 AI 工具。翻了一下,我的 API Key 散布在以下地方:
# .env 文件(4个项目里各有一份)
OPENAI_API_KEY=sk-xxxx
ANTHROPIC_API_KEY=sk-ant-xxxx
GOOGLE_AI_KEY=AIzaSy-xxxx
# ~/.zshrc(是的我干了这种蠢事)
export DEEPSEEK_API_KEY="sk-xxxx"
# VS Code settings.json
"copilot.apiKey": "xxx"
# 某个 Jupyter Notebook 里硬编码的
client = OpenAI(api_key="sk-proj-xxxxx")
# Chrome 密码管理器里存的各平台 dashboard 密码
# ...懒得数了
数了一下,7 个不同平台的 API Key,分散在至少 12 个文件里。有的还提交过 git(虽然后来 force push 删了,但 GitHub 的搜索引擎可不会帮你删缓存 🫠)。
被偷家的三种姿势
看完那篇供应链攻击分析,我总结了下 API Key 被盗的三大路径:
1. 插件/扩展偷你 🔌
就是今天热搜上的这种。AI 编程插件天然需要读你的代码文件,你根本分不清它是在"帮你补全"还是在"偷你文件"。
恶意插件的操作:
- 监控
onDidChangeTextDocument,每次你编辑文件就把内容传出去 - 批量扫描
.env、config.json、SSH 密钥 - 用零像素 iframe 做用户画像
最恐怖的是:这些插件功能完全正常,能用,好用,你完全不会怀疑它。
2. 项目文件泄露 📁
这个是我自己的血泪教训:
# 你以为 .gitignore 了就安全?
$ git log --all --full-history -- "*.env"
# 惊不惊喜,意不意外
commit 3a7f2d1 Add environment config
.env | 15 +++++++++++++++
Git 历史是永久的。我之前有个项目忘了 gitignore .env,push 之后才发现,虽然马上删了,但那个 commit 还在历史里。GitHub 的代码搜索能搜到,各种爬虫也能搜到。
后来我装了 gitleaks 做 pre-commit 检查,现在每次 commit 前自动扫描敏感信息:
# 安装 gitleaks
brew install gitleaks
# 扫描历史提交
gitleaks detect --source . -v
# 作为 pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.0
hooks:
- id: gitleaks
3. 多平台 Key 管理混乱 🔑
这个是独立开发者的通病。你同时用 OpenAI、Anthropic、Google、DeepSeek、Moonshot……每个平台一套 key,每个项目一份 .env。
问题来了:
- 你怎么知道哪个 key 还在用?
- 哪个 key 额度快用完了?
- 哪个 key 可能已经泄露了?
- 某个平台 API 挂了,你怎么快速切换?
我之前的方式是全手动管理——一个 Notion 表格记着所有 key。你猜怎么着?Notion 链接分享的时候不小心开了公开访问 😇 还好及时发现了。
我的解决方案(踩了一个月的坑总结的)
折腾了一圈,我现在的 key 管理方案分三层:
第一层:本地环境加固
# 1. 所有 key 统一放 .env,不放 .zshrc
# 2. .gitignore 必须包含
.env
.env.*
*.pem
*.key
# 3. gitleaks pre-commit hook(上面说了)
# 4. 定期扫描
gitleaks detect --source ~/projects -v --no-git
第二层:用密钥管理工具
macOS 用户可以用 Keychain:
import keyring
# 存
keyring.set_password("openai", "api_key", "sk-xxxx")
# 取
key = keyring.get_password("openai", "api_key")
或者用 direnv + .envrc:
# .envrc(自动加载,离开目录自动卸载)
export OPENAI_API_KEY=$(security find-generic-password -s "openai-key" -w)
第三层:用聚合平台统一管理
这是我最近发现的思路,也是对我帮助最大的。
与其管 7 个平台的 key,不如只管 1 个。
现在有一些 AI 模型聚合平台,一个 API Key 就能调 GPT-4o、Claude、Gemini、DeepSeek 等几十个模型。我试了几家,目前主要在用的方案:
| 特点 | 分散管理 | 聚合平台 |
|---|---|---|
| Key 数量 | 7+ 个 | 1 个 |
| 泄露风险 | 高(散布各处) | 低(一个入口) |
| 模型切换 | 改代码 + 换 key | 改一个参数 |
| 额度监控 | 各平台分别看 | 统一 dashboard |
| 国内访问 | GPT/Claude 要翻墙 | 直连(有国内节点的话) |
我现在个人项目的调用方式统一成了 OpenAI 兼容格式,换模型只改 model 参数:
from openai import OpenAI
# 一个 key,几十个模型随便切
client = OpenAI(
api_key="your-one-key",
base_url="https://api.ofox.ai/v1" # 聚合平台地址
)
# 用 GPT-4o
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "hello"}]
)
# 切 Claude?改一行
resp = client.chat.completions.create(
model="claude-sonnet-4-5-20250929",
messages=[{"role": "user", "content": "hello"}]
)
# 切 DeepSeek?再改一行
resp = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": "hello"}]
)
不用管每个平台的 SDK 差异、不用管翻墙、不用管 key 过期轮换,对于我这种同时用好几个模型的人来说简直是救命。而且最关键的——我只需要保护好一个 key,安全管理的复杂度直接降了一个量级。
最后的碎碎念
说真的,今天那篇供应链攻击的文章让我挺后怕的。我们每天用各种 AI 工具写代码,却很少想过这些工具本身是否安全。
几个 takeaway:
- VS Code 插件不是装越多越好。不用的赶紧删,尤其是那些要读你代码的 AI 插件,认准官方的
- 别在 .zshrc 里 export API Key 了,真的会被读到的
- gitleaks 装一个,5 分钟的事,可以救你一命
- Key 管理要集中化,散落在 12 个文件 7 个平台的 key,你迟早管不过来
- 定期轮换 Key,别一个 key 用一年从不换
你的 API Key 管理方案是什么样的?有没有踩过类似的坑?评论区聊聊 👇
作者是一名独立开发者,日常折腾 AI 编程工具和各种大模型 API。关注我,下次聊聊 Vibe Coding 的正确打开方式。