概述
密钥通常通过普通提交泄露:调试时提交的 .env、测试里写死的 token、粘贴到脚本中的连接串。评审者关注逻辑而非字符串,因此这些内容会顺利进入 main。一旦推送,密钥就存在于每个克隆、每份 CI 缓存,甚至每个 fork 中。提交时扫描是移除成本最低的时机。gitleaks 依据已知凭证格式与熵启发式检查差异,可在本地、pre-commit 钩子和 CI 中使用同一套规则。
步骤
- 本地扫描完整历史,并在输出中打码:
gitleaks detect --source . --redact --verbose
- CI 中只扫描本分支新增的提交:
gitleaks detect --source . --log-opts "origin/main..HEAD" --redact --exit-code 1
- 添加 pre-commit 钩子,让密钥连本地提交都无法产生:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: gitleaks
- 先轮换凭证,再从历史中移除文件:
git filter-repo --path .env --invert-paths
验证
干净仓库的扫描应返回 0;引入测试 token 后,CI 任务应以退出码 1 失败,并只显示规则、文件与提交,不显示明文。pre-commit 钩子应在提交阶段直接拒绝。若 CI 通过而本地失败,通常是 CI 使用了浅克隆或不同提交范围,需要设置 fetch-depth: 0 并扫描正确的区间。
注意事项
- 模式匹配与熵检测无法覆盖看起来像普通文本的密钥。
- 从历史中删除不等于作废,轮换必须最先执行。
- 误报只允许按具体指纹或路径加入白名单,并写明原因。
- 密钥一旦暴露在推送中,应视为已泄露并评估影响范围。
- 定期做一次全历史扫描,作为门禁上线前遗留问题的兜底。