夜雨聆风学习资料网

ARTICLE · 1318762

一把我以为删掉的密钥,被 AI 工具复制了 17 份

一把我以为删掉的密钥,被 AI 工具复制了 17 份

QUOTE

把 key 放进 .env,早就不算安全实践,只是把风险挪了个文件夹。

—— 3182 个文件的盘点账

10 月 24 日,晚上十点半。我在改一个排行榜接口,手机弹出某云厂商的邮件:「检测到您的 API Key 在公开渠道出现」。

心脏骤停两秒。点进去一看,是扫到了我两年前传的一份教程示例仓库,里面那把 key 早在 2 月就吊销了。虚惊一场。

但虚惊之后我睡不着了。10 月接连出了好几起密钥相关的事件——Railway 泄了部分客户的环境变量,LiteLLM 的投毒版本专门搜刮 AI 厂商的 key。这些我都只是看的公开报道,细节以官方报告为准,但有一件事不用等报告:我的开发机上跑着三个 AI 编程工具、七八个 MCP server,它们读文件、跑命令、写日志——我的 key 到底散在这台机器的哪些地方?

我原来以为答案很简单:.env,加上工具自己的配置文件。第二天我请了半天假,把开发机翻了一遍。结论让我后背发凉:47 个目录、3182 个文件里,藏着 17 处明文密钥,对应 6 把不同的真 key。其中一把,我以为它 2 月就死了。

— 17 处明文密钥的 6 类藏身处;橙色是这篇的主角

本文看点

01

17 处密钥的 6 类藏身处

02

一把「死」了 8 个月的 key

03

我为啥弃用了全盘扫描

01

THE SHALLOW END

最浅的一层:配置文件里的 5 份

先说最容易想到的地方。我的 MCP 配置里躺着 5 份明文:两份在项目的 .mcp.json(一个数据库连接串和一张地图服务的 key),三份在用户目录的工具配置里。

这不是我手滑——装 MCP server 的时候,README 就是教你把 key 直接粘进 JSON 的,我照做了,一照做了两年。照着官方文档装工具,本身就会制造密钥副本。

后来我去查了个数:GitGuardian 统计过,2025 年公开的 GitHub 上,MCP 配置文件里躺着 24008 个独一无二的明文密钥,其中 2117 个至今仍然有效。我不孤独,我只是大多数。

这 5 份我全改成了环境变量引用,花 40 分钟。

02

DEEPER DOWN

稍深的一层:历史和会话里的 7 份

再往下翻,事情开始不对劲了。

shell 历史里 4 份

都是 export XXX_API_KEY=sk-xxx 这种命令,最早一条是去年 3 月的。我从来没意识到,每次在终端手动 export 一把 key,它就被永久抄送进 .bash_history——还会跟着 dotfiles 仓库同步到我另外两台机器。

AI 工具的会话文件里 3 份

这个最意外。有个工具会把会话期间的环境变量抓进项目目录下的状态文件,我 2 月在终端 export 过一把测试 key,被它抓走了,就躺在那个我从来没打开过的 json 里。要不是这次盘点,它会一直躺下去。

这 7 份的处理麻烦一些:历史文件清掉对应行,状态文件直接删,两台同步机器各清一遍,1 小时。

顺带说一句,这两类位置都没有任何工具提醒过我。pre-commit hook 只盯着 git,而 AI 工具从来不走 git。

03

THE UNDEAD KEY

最深的一层:一把死了 8 个月的 key

真正让我后背发凉的,在最深处。

一个云厂商工具的目录里,躺着一份 .bak——某次改配置时自动生成的备份文件,里面明文写着一把 key。我盯着它看了十秒钟,因为这把 key 我 2 月就吊销了。我以为。

— 扫描命中现场:这份 .bak 躺在工具目录里,从没被任何流程碰过

登录厂商后台查调用记录:最后一次调用是 1 月 28 日。也就是说,这把 key 从 2 月起就以「已吊销」的状态在我的硬盘上活着,活了 8 个月。万幸它是真被吊销了,硬盘上这份只是一具尸体。但那个瞬间我想明白一件事:

「我以为「吊销了」的东西,和我实际验证过「死了」的东西,中间隔着一整个硬盘。」

顺带一提,废弃项目里还翻出 1 份 .env,是去年 11 月烂尾的一个 side project。加起来正好 17 份。

账单没爆不是你安全,多半是你运气好。我的运气在 10 月 24 日用掉了一次,我不想再赌第二次。

04

THE 91% NOISE

我弃用了全盘扫描

处理完之后我想了个一劳永逸的办法:拿 gitleaks 全盘扫一遍,以后每周扫一次。

结果它给我吐了 3900 多行输出——测试 fixture、示例文档、我自己写的假 key,91% 是噪音,人工核了四十分钟核到眼瞎,第二周再跑又多出一堆新噪音。

第三周我把全盘扫描弃用了。改成笨办法:自己写了个 80 行的脚本,只扫 6 类白名单路径(MCP 配置、shell 历史、AI 工具状态目录、日志目录、.env、.bak 备份),10 秒跑完,输出不超过 20 行,每一行都值得看。

MISTAKE · 弃用判断

安全工具的产出如果九成是噪音,它就不是在帮你,是在训练你忽略警报。全盘扫描这个思路对仓库是对的,对整台机器是错的——机器上大部分「命中」本来就不是风险,真正会咬人的只有那 6 类路径。

05

THE RULES

三条规矩,和 3.5 小时的账

盘点加清理,总共花了 3.5 小时。6 把 key 全部轮换,每把设了月消费上限——对齐历史月均的 2 倍。钱一分没花,纯时间。

位置
份数
处置方式
耗时
MCP / 工具配置
5
改为环境变量引用
40 分钟
shell 历史
4
清行 + 3 台机器同步清
30 分钟
AI 会话状态文件
3
直接删除
15 分钟
工具日志
2
删除 + 关调试输出
10 分钟
.bak 备份
2
删除 + 轮换对应 key
20 分钟
废弃项目 .env
1
项目归档时一并销毁
5 分钟

改了 11 处配置,另外 6 份副本直接删了。之后我给自己立了三条规矩:

— 每把 key 的处置闭环:吊销不是终点,验证才是

1

key 只活在环境变量里。任何配置文件只允许出现变量引用;装新 MCP server 时 README 让粘 key,我粘引用。

2

每把 key 必须有消费上限和独立的用量面板。账单异常要能在当天定位到具体哪把 key,不做合并大账。

3

每个季度跑一次那个 80 行的脚本。吊销 key 之后必须验证——查调用记录,确认它真死了。

— 三条规矩贴在工位上,比任何安全工具都管用

∞

THE TAKEAWAY

写在最后

最后说个可能会被反驳的判断:在 AI 工具遍地读写文件的今天,把 key 放进 .env 已经算不上安全实践,它只是把风险从一个文件夹挪到了另一个文件夹。真正的分界线不是文件藏得好不好,而是这把 key 泄了之后,你多久能知道、多快能掐断。

这个判断的边界我也说清楚:我的样本只有一台开发机、3 年的使用痕迹、17 处命中,而且我是单兵作战,没有团队级的密钥管理平台。如果你在管一个团队的机器,结论大概率更难看。

你的机器上跑着几个 AI 工具?那 6 类位置,你敢说你全翻过吗?评论区聊聊你查到的最意外藏身处,我挑几个典型的整理成一篇续篇。

END

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料