适用对象:个人开发、小规模运营中使用 Git,并且担心『会不会不小心把 API 密钥提交上去』的人。本文不讲攻击方的手法,只讲阻止密钥从自己的仓库流出的机制。
本站的视角:光靠 .gitignore 守不住密钥
常听到有人说『我把 .env 放进 .gitignore 了所以没问题』,但这是有漏洞的。.gitignore 只是不把新文件纳入追踪而已,对已经提交的密钥、赶时间用 git add -f 强制添加的密钥、以及像 .env.local.bak 这种意料之外的文件名都抓不住。gitignore 只堵住了『入口的一部分』。真正去看提交内容、检出『看起来像密钥的字符串』的机制——也就是检测器——还得另外配一个。这正是 gitleaks 的职责。
为什么要在『提交前』拦住
密钥之所以危险,是因为 Git 会永久保留历史。即使从最新文件里删掉,过去的提交里还留着。而且在 push 的那一刻,那段历史就会被复制到他人的本地、服务器以及 CI 的日志里。
也就是说,密钥防护的正道不是泄露后的回收,而是泄露前的阻止。这跟『别把密钥忘在公开目录里』的盘点(→ webroot 的盘点)是同一个思路,只是把它搬到了代码的世界。
拦截点在哪里
在密钥从代码流向外界的路径上,可以设两道拦截点。本地提交时,以及被共享之前(CI)。
代码里的密钥
API 密钥、私钥、token
门 1:pre-commit
提交时在本地检出并中断
门 2:CI / cron
push 后在合并/部署前检出
公开・共享
到这一步就要按已泄露处理
gitleaks 的集成方式
先扫描现有历史
gitleaks detect 扫描一次。把过去提交里潜伏的密钥翻出来,是第一件要做的事。这里找到的东西,正如后文所述以吊销为前提。用 pre-commit 钩子建好门 1
gitleaks protect --staged,当场中断含密钥的提交。加到 pre-commit 框架(.pre-commit-config.yaml)里,团队和本地就都会跑同一套检查。用 CI / cron 建好门 2
gitleaks detect 抓住漏网之鱼(→ 跟依赖审计一样,是机器监控的思路)。误报用 .gitleaks.toml 调整
.gitleaks.toml 来调整。不是『让它闭嘴』,而是『记录下为什么它是安全的』才是正确的运维——没有依据的排除会成为下一次事故的温床。检出后先『吊销』,改写历史在后
一旦发现已被提交、push 的密钥,最优先的是吊销并重新签发(轮换)那个密钥/token。用 git filter-repo 等从历史里删掉固然重要,但那只是为了『不再扩大』的善后处理。要认为已经流到公开仓库、fork、CI 日志、他人 clone 里的密钥无法回收,请先作废再去清理历史。顺序反了的话,你删的时候它已经被人用了。
只靠 .gitignore
- 只能防住新的追踪
- 已经提交的密钥直接放行
- 对
git add -f或意料之外的文件名无能为力 - 无法验证『我以为没放进去』
gitleaks(检出+吊销运维)
- 实际检查工作树和历史的内容
- 用 pre-commit 和 CI 两道拦截
- 检出后把直到吊销的步骤流程化
- 误报记录依据后再排除
本站是怎么做的
本站从根本上以密钥一概不放进 Git 的设计为基础——连接信息和 API 密钥只放在服务器上受保护的配置里(权限收紧的环境文件),既不在仓库里、也不在交接资料里留明文(→ 不把密钥放进 git/自建 Git vs GitHub)。在此之上,再以人一定会犯错为前提叠加检测器。用设计保证『不放进去』,用 gitleaks 这类扫描抓住『还是放进去了』——这两层,就是本站面对密钥泄露的防守。密钥处理的原则本身,跟 .env 与密钥信息 以及 安全保存密码 也是一脉相承的。
接下来阅读
FAQ
Qgitleaks 是什么?
它是一款免费工具,会扫描 Git 仓库的工作树和提交历史,检出是否有 API 密钥、私钥、token 等密钥被提交。它通过正则规则和字符串的熵(随机度)来找出『看起来像密钥的字符串』,可以集成进 pre-commit 钩子或 CI 进行自动检查。
Q只要写进 .gitignore 就能守住密钥吗?
不够。.gitignore 只是『不把新文件纳入追踪』而已,对已经提交的密钥、或用 git add -f 强制添加的密钥无能为力。gitignore 只能挡住一部分事故,所以要把像 gitleaks 这样的检测器放进 pre-commit 和 CI 做双重保险。
Q不小心把密钥提交并 push 了怎么办?
要把那个密钥当作『已经泄露』来处理。最优先的不是改写历史,而是吊销并轮换(重新签发)泄露的密钥/token。要认为一旦进入公开仓库或日志的密钥就再也收不回来,先把它作废,之后再清理历史并做防复发(引入 gitleaks)。