本文目录导读:

核心检查逻辑
- 获取待提交的文件内容(暂存区的内容)
- 用正则或关键词匹配敏感信息模式
- 若有匹配则阻止提交,并提示具体违规行
常用钩子:pre-commit
最常用的是 pre-commit 钩子,在提交前对暂存区内容进行扫描。
示例脚本(Bash)
创建文件 .git/hooks/pre-commit(需赋予执行权限 chmod +x):
#!/bin/bash
# 防泄漏检查脚本示例
# 定义需要检查的敏感模式(可根据业务扩展)
SENSITIVE_PATTERNS=(
"(?i)(password|passwd|pwd)\s*[:=]\s*['\"][^'\"]+['\"]"
"(?i)(secret|api.?key|access.?key|auth.?token)\s*[:=]\s*['\"][^'\"]+['\"]"
"(?i)(AKIA[0-9A-Z]{16})" # AWS Access Key 示例
"-----BEGIN (RSA|EC|OPENSSH|DSA) PRIVATE KEY-----"
"ghp_\w{36}" # GitHub Personal Access Token
"gho_\w{36}" # GitHub OAuth Token
"sk_live_\w{24}" # Stripe Live Secret Key
"xox[barp]-[0-9a-zA-Z-]{10,}" # Slack Token
)
# 颜色输出
RED='\033[0;31m'
NC='\033[0m' # No Color
# 获取暂存区中新增或修改的文件(只处理文本文件)
files=$(git diff --cached --name-only --diff-filter=ACM)
# 标记是否有违规
has_violation=false
for file in $files; do
# 跳过二进制文件(避免误判)
if [[ "$file" =~ \.(png|jpg|jpeg|gif|ico|svg|woff|eot|ttf|pdf|zip|tar|gz|exe|bin)$ ]]; then
continue
fi
# 读取暂存区文件内容(而非工作区)
content=$(git show :"$file" 2>/dev/null)
if [ -z "$content" ]; then
continue
fi
# 逐行检查
line_num=0
while IFS= read -r line; do
line_num=$((line_num + 1))
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if [[ "$line" =~ $pattern ]]; then
echo -e "${RED}[WARNING] 检测到疑似敏感信息${NC}"
echo " 文件: $file"
echo " 行号: $line_num"
echo " 匹配模式: $pattern"
echo " 内容: $line"
echo "----------------------------------------"
has_violation=true
fi
done
done <<< "$content"
done
if [ "$has_violation" = true ]; then
echo -e "${RED}提交被阻止:请移除或替换上述敏感信息后重试。${NC}"
exit 1
fi
exit 0
更强大的工具:使用 gitleaks 或 talisman
手动写正则容易遗漏或误报,推荐集成专业工具:
使用 gitleaks(推荐)
# 安装 gitleaks
# macOS: brew install gitleaks
# Linux: 下载二进制或 go install github.com/gitleaks/gitleaks/v8@latest
# pre-commit 脚本中调用
#!/bin/bash
gitleaks detect --source . --staged --verbose
if [ $? -eq 1 ]; then
echo "检测到潜在敏感信息,请审查并修复后重新提交。"
exit 1
fi
使用 talisman
# 安装: curl -s https://thoughtworks.github.io/talisman/install.sh | bash
# 会在 .git/hooks/ 下自动安装 pre-commit 钩子
# 或手动调用:
#!/bin/bash
talisman --scan --staged
if [ $? -ne 0 ]; then
exit 1
fi
进阶处理
允许特定文件跳过检查(白名单)
# 在 pre-commit 脚本中增加跳过逻辑
skip_files=("CHANGELOG.md" "*.example.*")
for skip in "${skip_files[@]}"; do
if [[ "$file" == $skip ]]; then
continue 2
fi
done
使用 .gitallowed 或 .secretsignore 文件
- 在项目根目录创建
.gitallowed(talisman 支持) - 或在
.gitleaksignore中记录已审查的 false positive
提交前自动替换敏感占位符
可以在 pre-commit 中自动将 password = "realpass" 替换为 password = "xxx" 再提交(需谨慎,可能破坏代码)。
注意事项
| 问题 | 建议 |
|---|---|
| 误报 | 设置白名单或使用 .gitallowed 忽略已知占位符 |
| 性能 | 只检查暂存区文件(git diff --cached),避免全量扫描 |
| 二进制文件 | 跳过图片、压缩包等非文本文件 |
| 大文件 | 可设置文件大小限制,超过则忽略 |
| CI/CD 兼容 | 在 CI 中也加入同样的扫描步骤,防止绕过本地钩子 |
最佳实践总结
- 本地 + 远程双重防护:本地
pre-commit+ CI/CD 管道中再次扫描 - 使用成熟工具:
gitleaks或talisman比手写正则更全面 - 定期更新规则:敏感信息模式会变化,保持规则库更新
- 培训团队:让开发者了解常见泄漏场景,减少无意提交
通过以上方式,可以有效防止敏感信息进入版本控制历史。