8.4.4 代码提交前自动检查——防误提交
.gitignore 是第一道防线,pre-commit 检查是第二道——双重保险防止敏感文件进入仓库。
为什么需要 pre-commit 检查
| 场景 | 问题 | 解决方案 |
|---|---|---|
| 忘记添加 .gitignore | 新文件类型被提交 | 自动扫描敏感模式 |
| 绕过 .gitignore | git add -f 强制添加 | hook 拦截 |
| 大文件意外提交 | 仓库变臃肿 | 文件大小检查 |
| 敏感信息硬编码 | 密钥写在代码里 | 模式匹配检查 |
使用 husky 配置 pre-commit
安装配置
bash
# 初始化 husky
pnpm add -D husky
pnpm exec husky init创建敏感文件检查脚本
创建 scripts/check-secrets.sh:
bash
#!/bin/bash
# 检查是否有敏感文件被暂存
SENSITIVE_PATTERNS=(
"\.env$"
"\.env\.local$"
"\.pem$"
"\.key$"
"id_rsa"
"\.p12$"
"credentials\.json"
"firebase.*\.json"
)
STAGED_FILES=$(git diff --cached --name-only)
FOUND_ISSUES=0
for file in $STAGED_FILES; do
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if [[ $file =~ $pattern ]]; then
echo "❌ 敏感文件被暂存: $file"
FOUND_ISSUES=1
fi
done
done
if [ $FOUND_ISSUES -eq 1 ]; then
echo ""
echo "请使用 'git reset HEAD <file>' 移除敏感文件"
echo "如果确实需要提交,请使用 'git commit --no-verify'"
exit 1
fi
echo "✅ 敏感文件检查通过"配置 pre-commit hook
编辑 .husky/pre-commit:
bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# 敏感文件检查
bash scripts/check-secrets.sh
# lint-staged(如果配置了)
pnpm exec lint-staged检查硬编码的密钥
使用 gitleaks
bash
# 安装 gitleaks
brew install gitleaks
# 在 pre-commit 中添加检查
gitleaks protect --staged配置 .gitleaks.toml
toml
title = "Gitleaks Config"
[[rules]]
description = "AWS Access Key"
regex = '''AKIA[0-9A-Z]{16}'''
tags = ["aws", "key"]
[[rules]]
description = "OpenAI API Key"
regex = '''sk-[a-zA-Z0-9]{48}'''
tags = ["openai", "key"]
[[rules]]
description = "Generic Password"
regex = '''(?i)(password|pwd|pass)\s*[:=]\s*['"][^'"]{8,}['"]'''
tags = ["password"]大文件检查
bash
#!/bin/bash
# scripts/check-file-size.sh
MAX_SIZE=5000000 # 5MB
STAGED_FILES=$(git diff --cached --name-only)
for file in $STAGED_FILES; do
if [ -f "$file" ]; then
SIZE=$(wc -c < "$file")
if [ $SIZE -gt $MAX_SIZE ]; then
echo "❌ 文件过大: $file ($(( SIZE / 1000000 ))MB)"
echo "考虑使用 Git LFS 或添加到 .gitignore"
exit 1
fi
fi
done
echo "✅ 文件大小检查通过"CI 层面的检查
即使本地绕过了 hook,CI 也要有最后一道防线。
GitHub Actions 检查
yaml
# .github/workflows/security.yml
name: Security Check
on: [push, pull_request]
jobs:
secrets-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Gitleaks Scan
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
check-ignored-files:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for sensitive files
run: |
SENSITIVE_FILES=$(find . -type f \( \
-name ".env" \
-o -name ".env.local" \
-o -name "*.pem" \
-o -name "*.key" \
-o -name "id_rsa" \
\) 2>/dev/null)
if [ -n "$SENSITIVE_FILES" ]; then
echo "::error::Found sensitive files in repository:"
echo "$SENSITIVE_FILES"
exit 1
fi完整 pre-commit 配置
bash
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
echo "🔍 Running pre-commit checks..."
# 1. 敏感文件检查
echo "Checking for sensitive files..."
bash scripts/check-secrets.sh || exit 1
# 2. 大文件检查
echo "Checking file sizes..."
bash scripts/check-file-size.sh || exit 1
# 3. 密钥扫描(如果安装了 gitleaks)
if command -v gitleaks &> /dev/null; then
echo "Scanning for secrets..."
gitleaks protect --staged || exit 1
fi
# 4. 代码格式化和 lint
echo "Running lint-staged..."
pnpm exec lint-staged || exit 1
echo "✅ All pre-commit checks passed!"验收清单
- [ ] 配置了敏感文件的 pre-commit 检查
- [ ] 可选:配置了 gitleaks 密钥扫描
- [ ] 可选:配置了大文件检查
- [ ] 配置了 CI 层面的安全扫描
