提交前的密钥扫描与敏感信息检测:别让 API key 跟着代码一起泄出去
把硬编码的 API key、AWS 凭证、token 和私钥找出来,讲清楚 AKIA、sk- 这类已知前缀和高熵字符串怎么识别,以及怎么在本地扫描、提交前自查、不上传任何内容。
提交前的密钥扫描与敏感信息检测:别让 API key 跟着代码一起泄出去
凭证泄漏几乎都不是黑客攻进来的,而是自己人随手提交出去的。一行写死的 AWS_SECRET_ACCESS_KEY,一段失败 curl 命令打进 CI 日志,一个本该是占位符却填了真实值的 .env.example,这些东西一旦进了公开仓库或外发的日志包,机器人几分钟内就会扫到。所以真正有效的防线,是在 git commit 之前自己先扫一遍。
泄漏最常发生在哪三个地方
第一是代码本身。开发时为了跑通,把 token 直接写进源文件,准备"待会儿改成环境变量",然后就忘了。第二是配置文件。.env、config.yaml、docker-compose.yml 这些文件经常被误加进版本控制,或者示例文件里塞了真实值。第三是日志。CI 跑失败后,展开的环境变量、数据库连接字符串、带 token 的请求头会原样打进日志,而日志包又最容易被随手转发给同事或贴进工单。
这三处的共同点是:它们都不是"敏感文件",平时没人盯,所以恰恰是泄漏的高发区。
已知密钥前缀:认前缀比认正则快
很多厂商的凭证有固定前缀,这是扫描里命中率最高的一类。AWS 的 access key ID 以 AKIA 开头,后面跟 16 位大写字母和数字。OpenAI 风格的 API key 以 sk- 开头。GitHub 的 token 以 ghp_、gho_、ghs_ 这类前缀打头。Stripe 的密钥分 sk_live_ 和 sk_test_,前者是生产环境真金白银。Slack 的 token 以 xoxb-、xoxp- 开头。Google API key 通常是 AIza 起头的一长串。
只要文本里出现这些前缀加上对应长度,基本就能锁定是凭证,不是随便一个字符串。
没有前缀的密钥靠高熵字符串识别
不是所有密钥都带前缀,数据库密码、自定义 token、私钥块就没有。这时要看两个信号。一个是赋值上下文,比如 password=、secret=、api_key=、token=、client_secret= 后面跟着的值,本身就值得警惕。另一个是高熵字符串,也就是看起来像随机生成的长串字符:大小写混排、夹着数字和符号、没有明显单词结构。一段 40 位的随机十六进制或 base64,几乎不可能是普通配置项,熵值高就是密钥的特征。私钥则更直接,-----BEGIN ... PRIVATE KEY----- 这种块只要出现就是命中。
ENV 密钥扫描器 把这两类逻辑都做进去了:既匹配 AWS、GitHub、Stripe、Slack、Google、OpenAI 这些固定前缀和私钥块、JWT、数据库 URL,也识别 secret、token、password、api key、client secret 这类可疑赋值。
一个真实例子:从一段配置里扫出硬编码 key
假设有人在提交前把下面这段贴进扫描器:
# config/app.py
DEBUG = True
DATABASE_URL = "postgres://admin:S3cr3tP@ss@db.internal:5432/prod"
AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"
STRIPE_KEY = "sk_live_4eC39HqLyjWDarjtT1zdp7dc"
# TODO: 上线前改成读环境变量
openai.api_key = "sk-proj-abc123def456ghijklmnopqrstuvwxyz0123"
扫描会逐行标出位置:第 3 行的 DATABASE_URL 是带账号密码的连接字符串,第 4 行 AKIAIOSFODNN7EXAMPLE 命中 AWS access key ID 前缀,第 5 行 sk_live_ 是 Stripe 生产密钥,第 6 行 sk-proj- 是 OpenAI key。那句"上线前改成读环境变量"的注释,正是这类泄漏的典型现场:本来打算改,结果连同 key 一起提交了。报告里这些值会默认打码,你可以放心把扫描结果转给同事确认,不会二次暴露。
我自己提交前的习惯
我现在的流程很简单:git add 之后、git commit 之前,先 git diff --cached 看一眼这次到底改了什么,再把可疑的配置段、改动过的 .env 片段、最近一次失败的 CI 日志贴进扫描器跑一遍。有一次我就是这么逮到一个写死在测试脚本里的 Slack xoxb- token,那是几周前调试时图省事填的,早忘了。要是没扫,它会跟着一次很普通的重构 PR 一起进主分支。多花三十秒,省掉的是事后轮换密钥、排查泄漏范围、写复盘的几个小时。
为什么坚持本地扫描、不上传
把含密钥的配置贴到在线服务去检测,这件事本身就矛盾:你为了确认有没有泄漏,反而先把它发给了第三方。正确的做法是扫描全程在浏览器本地完成,文本不离开你的机器,发现项还默认打码。这样无论是公司内部代码还是个人项目,都不会因为"做安全检查"而制造新的暴露面。
如果扫出来的是一段 JWT,想看清里面到底带了哪些 claim、有没有把敏感字段塞进 payload,可以用 JWT 解码器 在本地拆开看,同样不上传。
最后提醒一句:扫描没发现不等于绝对干净,自定义格式的密钥仍可能漏掉;而一旦确认某个值是真实凭证且已经提交、记录或外发过,光从代码里删掉不够,必须去对应平台轮换它。
Made by Toolora · Updated 2026-06-13