Security
Git 密钥扫描与泄露防护
密钥如何泄露到 Git、git-secrets、truffleHog、Gitleaks 自动扫描、平台级检测、BFG 历史清理与 pre-commit 预防机制。
- 需要配置 Git 安全认证的开发者
- 知道 SSH 的基本概念
- 有命令行操作经验
- 密钥管理不当导致安全泄露
- 不理解签名策略导致提效验证失败
学完这篇你会掌握什么
- 理解 Git 密钥扫描与泄露防护 的核心作用和适用场景
- 掌握 Git 密钥扫描与泄露防护 的基本用法和常用参数
- 密钥如何泄露到 Git、git-secrets、truffleHog、Gitleaks 自动扫描、平台级检测、BFG 历史清理与 pre-commit 预防机制。
- 理解 密钥如何泄露到 Git 相关的概念
- 掌握 git-secrets 相关的操作
- 知道在什么场景下使用该命令,什么场景下避免使用
先想一个问题
你担心 Git 仓库的安全——可能是密钥管理不到位,也可能是提交没有签名验证。你不确定自己的安全配置是否足够,也不清楚从哪里开始加固。
一句话理解
API 密钥、密码、令牌等敏感信息一旦误提交到 Git,将永久存在于历史记录中——自动化扫描、提交前钩子和历史清理工具是三道关键防线。
密钥如何泄露到 Git
# 常见泄露场景:
git add . # 误将 .env 添加到暂存区
git commit -m "fix config" # config 文件包含硬编码密钥
git push origin main # 密钥已经公开
即使在后续提交中删除了文件,密钥仍然存在于对象数据库中:
git log --all --diff-filter=D --summary # 查找已删除文件
git show COMMIT_HASH:config.js # 密钥仍然可见
git-secrets
通过正则匹配在提交前和历史中扫描敏感信息。
# 安装
brew install git-secrets # macOS
sudo apt install git-secrets # Linux
# 注册 AWS 模式
git secrets --register-aws
# 安装 pre-commit 钩子
git secrets --install
# 扫描整个历史
git secrets --scan-history
# 添加自定义模式
git secrets --add 'api[_-]?key\s*[:=]\s*.+'
git secrets --add '(--|password|passwd)\s*[:=]\s*.+'
truffleHog
基于熵值检测——无需预定义模式,自动发现高熵字符串。
# 扫描仓库
trufflehog git https://github.com/user/repo.git
# 指定分支扫描
trufflehog git https://github.com/user/repo.git --branch main
# 扫描本地目录
trufflehog filesystem /path/to/repo
Gitleaks
基于规则的扫描工具,内置大量检测规则。
# 安装
brew install gitleaks
# 扫描仓库
gitleaks detect --source . -v
# 使用自定义配置
gitleaks detect --source . --config .gitleaks.toml
# 扫描全部历史
gitleaks detect --source . --log-opts="--all"
# 导出 JSON 报告
gitleaks detect --source . --report-format json --report report.json
.gitleaks.toml 示例:
title = "自定义 Gitleaks 配置"
[[rules]]
id = "custom-api-token"
description = "自定义 API 令牌模式"
regex = '''(?i)myapp_token[ =]+[0-9a-zA-Z_-]{20,}'''
tags = ["custom", "token"]
[[rules]]
id = "private-key"
description = "私钥块"
regex = '''-----BEGIN\s?RSA\s?PRIVATE\s?KEY-----'''
tags = ["key", "crypto"]
平台级检测
GitHub Secret Scanning
自动扫描所有公开仓库,匹配已知合作伙伴模式(AWS、Google、Azure 等),同时通知用户和供应商。
# 在私有仓库中启用:
# Settings → Code security → Secret scanning → Enable
GitLab Secret Detection
通过专用 CI 任务实现:
secret_detection:
stage: test
script:
- gitlab-org/ci-cd/secret-detection
rules:
- if: $CI_COMMIT_BRANCH == "main"
密钥相关 .gitignore 最佳实践
# 环境文件
.env
.env.*
.env.local
.env.production
# 密钥和凭据
**/secrets/
credentials.*
*.cred
**/config/credentials/
# 密钥文件
*.pem
*.key
*.p12
*.jks
id_rsa
id_ed25519
# 可能包含密钥的构建产物
*.log
npm-debug.log*
全局 .gitignore
git config --global core.excludesFile ~/.gitignore_global
Pre-Commit 钩子检测密钥
使用 pre-commit 框架:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: detect-private-key
- repo: https://github.com/awslabs/git-secrets
rev: master
hooks:
- id: git-secrets
手动 pre-commit 钩子(.git/hooks/pre-commit):
#!/bin/sh
git secrets --pre-commit
gitleaks protect --source .
从历史中移除密钥
BFG Repo-Cleaner
快速清理大文件或文本模式。
# 克隆镜像
git clone --mirror https://github.com/user/repo.git
# 替换敏感文本
java -jar bfg.jar --replace-text passwords.txt repo.git
# 删除特定文件
java -jar bfg.jar --delete-files .env repo.git
# 过期并垃圾回收
cd repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --force
git filter-repo
基于 Python 的更强大替代方案。
pip install git-filter-repo
# 从所有历史中移除文件
git filter-repo --path .env --invert-paths
# 替换文本
git filter-repo --replace-text <(echo "AKIAIOSFODNN7EXAMPLE==>REPLACED")
防止意外提交
使用凭据管理器代替硬编码令牌:
git config --global credential.helper osxkeychain
设置 pre-push 钩子:
#!/bin/sh
# .git/hooks/pre-push
git secrets --scan || exit 1
gitleaks detect --source . -v || exit 1
关键要点
- 历史中的密钥是永久的——除非主动清理
- 平台扫描是被动的——能事后发现,不能事前预防
- Pre-commit 钩子最有效——在源头阻断泄露
- 任何泄露的密钥都视为已泄露——立即轮换
- 组合工具:git-secrets + Gitleaks + 平台扫描,纵深防御
给你的练习
- 在一个测试仓库中练习该命令的基本用法,观察执行前后的状态变化
- 尝试该命令的不同参数选项,对比输出结果的差异
- 模拟一个需要使用该命令的实际场景,完整走一遍操作流程
继续学习建议
best-practices/security-with-git— Git 安全最佳实践概览security/credential-helper— 凭据管理,避免硬编码security/gpg-signing— 提交身份验证commands/git-fsck— 仓库完整性检查