.env 删了还在历史里:我拿 gitleaks 扫了一遍自己的仓库
有个项目我一开始图省事,把 .env 一起提交了。后来意识到不对,加进 .gitignore、git rm --cached,以为干净了。
直到有人问了一句:那你之前那次提交呢?
删文件只是让最新一次提交里没有它,之前那些提交照样躺在历史里,git log -p 一翻就出来。仓库要是公开的,等于把密钥挂出去了。
所以我去找了个专门干这事的工具:gitleaks,三万多星,用 Go 写的单文件程序。
先装
最省事是下 release 里的二进制,扔进 PATH 就行。macOS 也可以用 brew:
brew install gitleaks
装完先确认版本能跑:
gitleaks version
第一次跑,先撞上命令改版
网上教程大多写的是 gitleaks detect。我照着敲,能用,但看帮助的时候发现它现在把扫描拆成了两个子命令,语义更清楚:
gitleaks git [flags] [repo] 扫 git 仓库的历史
gitleaks dir [flags] [path] 扫目录当前内容(不看历史)
dir 还有别名 file 和 directory,敲哪个都认。
这个区分很重要,也是我一开始没搞明白的地方:
- 要查「历史上有没有提交过密钥」→ 用
git - 要查「当前这些文件里有没有」→ 用
dir
我一开始跑的是 dir,扫完干干净净,还以为没事。换 git 再扫,出来三条。差别就在这。
扫当前仓库的历史
cd your-project
gitleaks git .
默认会扫全部分支的历史。输出是一行一条,带上文件、行号、规则名。找到的话退出码非 0,可以直接串在 CI 里。
想只扫最近一段,用 --log-opts 把参数透给 git log:
gitleaks git --log-opts="--since=2026-01-01" .
这个参数挺实用——大仓库全历史扫一遍很慢,日常检查扫最近几个月就够了。
提交前拦一道
git 子命令有个 --pre-commit,只扫 git diff 里改动的内容,速度很快,适合挂在 pre-commit 钩子上:
gitleaks git --pre-commit
挂在 .git/hooks/pre-commit 里,密钥就进不了提交。这比事后扫历史强——历史一旦推上去,清理成本高得多。
把结果存成文件
扫出来的东西要留档或者给同事看,加报告参数:
gitleaks git . --report-path=leaks.json --report-format=json
--report-format 支持 json / csv / sarif,sarif 可以直接喂给 GitHub 的代码扫描面板。
还有个 --platform 参数,填 github 或 gitlab,报告里会带上能直接点开的链接,省得自己拼 URL:
gitleaks git . --platform=github --report-path=leaks.sarif --report-format=sarif
三个容易忽略的点
一是扫出来不等于泄露。它靠正则和熵值判断,误报不少——测试用的假 key、文档里的示例 token 都会被标。看结果的时候要逐条确认,别看到红字就慌。
二是删文件不等于删历史。这是我最开始那个错误。真要清理,得改历史(git filter-repo 之类),而且改完所有人都要重新拉。
三是密钥一旦进过公开仓库,就应该当它已经泄露。清理历史是给仓库看的,密钥本身该换就得换——清理和轮换是两件事,别只做一件。
一个值得知道的事实
翻它 README 的时候看到一段提示:作者说 Gitleaks 已经功能完整,不再合并新功能,后续只发安全补丁,精力转去了另一个叫 Betterleaks 的项目。
这不影响现在用它——存量扫描、CI 拦截这些事它做得挺好,规则库也还在。但如果你的用法依赖它持续加新检测规则,得留个心,看看要不要跟新的那个。
顺便说一句,这类工具本质是「正则 + 熵检测」,换个工具思路都差不多。真正有用的不是记住哪个工具,是养成两个动作:提交前扫一遍,定期扫一遍历史。
- 点赞
- 收藏
- 关注作者
评论(0)