检查 AI 生成的代码有没有藏密钥:搜密钥特征;把密钥移到环境变量;连 Git 历史也要查;提交前先扫描

本文译自 kikomono.com 英文原文《Check AI-generated code for secrets before running it》,作者 Rita。原文链接:https://kikomono.com/ai-tools/check-ai-code-for-secrets-before-running/

AI 编程助手常常在能跑的示例里把 API 密钥和密码直接写进代码。运行或提交这段代码之前,先搜一遍凭证特征,把每个真密钥移到环境变量,再把整个改动——包括 Git 历史——扫一遍:密钥一旦进了仓库或浏览器,就等于已经泄露了。

为什么 AI 写的代码里会藏密钥

AI 助手从公开示例里学写代码,而很多教程为了让示例马上能跑,会把 API 密钥直接写进函数调用里。你让它接一个服务时,它常常照搬这个写法:一段能跑的代码,里面躺着明文凭证。代码能跑,看起来就没问题——直到文件被提交、分享,或发到浏览器里,任何能读到它的人也都能用这把密钥。

第二条路是你自己的输入。如果你为了让助手测通连接,把真密钥贴进了聊天,助手可能把它原样抄回给你的代码里。凡是在聊天里敲过的密钥,都当作已经传出去了;如果是生产环境的凭证,就轮换掉。

搜一搜你收到的代码

运行任何东西之前,先把整个改动里凭证可能藏的地方搜一遍。用编辑器的全文件搜索,别只搜助手改过的那个文件。

藏在哪里搜什么
代码里的赋值api_key、apiKey、secret、token、password 后面跟一长串值
已知密钥前缀sk_live_ 和 sk_test_(Stripe)、AKIA(AWS 访问密钥)、Bearer 令牌
连接字符串数据库或服务地址里的 user:password@host 形式
配置与测试文件配置文件、测试用例、种子数据和示例请求里的密钥
注释与文档注释、TODO、README 示例和 CI 文件里贴的真密钥
环境文件存在却从没进 .gitignore 的 .env 文件

某个名字旁边出现一长串看起来随机的字符串,先当它是凭证,除非能证明不是。YOUR_API_KEY_HERE 这样一目了然的占位符是安全的,它没有真值。分不清一串字符是真是假时,按真的处理,换掉它。

把密钥移出去,别只删掉那一行

从文件里删掉密钥,只修好了当前这一份;如果运行时还需要这个值,问题还在。耐用的修法是让代码引用密钥,而不是包含密钥:把值存在环境变量或密钥管理器里,代码从那里读。把 .env 文件写进 .gitignore,别进版本控制;再留一个 .env.example,只写占位符名字,不写真值。

构建产物也要查。打包工具可能把环境变量的值抄进发出去的 JavaScript,于是本来安稳待在本地文件里的密钥,变成了 dist 或 build 文件夹里的明文。如果构建产物提交进了仓库,推送之前用同样的特征搜一遍。

查 Git 历史,不只查当前文件

从最新提交里删掉密钥,不等于把它从仓库里删掉。任何人都能检出更早的提交,读到这个值。如果真密钥曾经提交过,先轮换或吊销这把密钥——这才是真正堵住泄露的修法——然后再清理历史。只删文件不轮换密钥,等于把一把能用的凭证留在公开的地方。

提交之前先扫描

手工搜能抓住你想到要找的东西;扫描器能抓住你没想到要打开的文件。Gitleaks 和 TruffleHog 这样的免费开源扫描器,会拿已知的凭证特征去查工作区和 Git 历史。提交之前对整个改动跑一遍,不是推送之后再跑。经常用 AI 生成的代码,就值得配一个提交前自动跑扫描的钩子:赶时间的提交也能被查到。

审稿时常问的问题

像 YOUR_API_KEY 这样的占位符算密钥吗?

不算。占位符没有真值,用它访问不了任何东西。风险在同一个位置上那串看起来是真的长字符串。接上真密钥时,把占位符换成环境变量引用。

从文件里删掉密钥就够了吗?

不够。Git 历史、构建产物和分享出去的副本里可能还留着它。先轮换或吊销密钥,再从代码和历史里清除。

能把真密钥贴进 AI 工具里测代码吗?

用测试密钥或占位符测。生产环境的密钥一旦敲进聊天,就等于传到了你控制范围之外,当作已泄露,轮换掉。

手工搜过了,还需要扫描器吗?

两个都要。手工搜帮你学会这些特征;扫描器会查每一个文件,包括你没打开过的测试数据、配置模板和历史。每次提交含 AI 生成代码的改动之前都跑一遍扫描。

适用范围与延伸阅读

我们的英文原文中的编程助手检查清单讲的是付费之前怎么评估一款助手。工具本身见英文原文中的 Cursor 指南和 GitHub Copilot 指南。把敏感材料上传到任何 AI 工具之前,先读英文原文中的上传前检查。

本页的来源链接不是联盟链接。这里提到的密钥前缀是各服务自己文档里的公开特征;使用任何服务之前,先以它的最新文档为准。