Git钩子脚本如何检查安全策略

wen 实用脚本 1

本文目录导读:

Git钩子脚本如何检查安全策略

  1. 禁止提交硬编码密码/密钥
  2. 使用专门的工具(更推荐)
  3. 文件类型与大小限制
  4. 提交信息安全审计
  5. 服务端 hook 安全策略(更严格)
  6. 完整的 hook 管理方案
  7. 最佳实践建议

Git 钩子(Hook)脚本非常适合在本地或服务端实施安全策略检查(如禁止提交硬编码密码、检测密钥文件、禁止敏感 API Token 等),以下是一些常见的安全策略检查实现方式。

禁止提交硬编码密码/密钥

pre-commit 钩子(客户端)

#!/bin/bash
# .git/hooks/pre-commit
# 定义需要检测的模式(正则表达式)
PATTERNS=(
    "password\s*[:=]\s*['\"]?\w+['\"]?"   # 通用密码
    "api.?key\s*[:=]\s*['\"]?\w+['\"]?"   # API Key
    "secret\s*[:=]\s*['\"]?\w+['\"]?"     # Secret
    "token\s*[:=]\s*['\"]?\w+['\"]?"      # Token
    "-----BEGIN RSA PRIVATE KEY-----"     # 私钥
    "AKIA[0-9A-Z]{16}"                    # AWS Access Key
)
# 获取暂存区中的文件变更
FILES=$(git diff --cached --name-only --diff-filter=ACM)
for file in $FILES; do
    # 排除一些文件类型(如 .min.js, .lock 等)
    if [[ "$file" =~ \.(min\.js|lock|sum|hash)$ ]]; then
        continue
    fi
    # 检查文件中是否包含敏感模式
    for pattern in "${PATTERNS[@]}"; do
        if git diff --cached -U0 "$file" | grep -qE "$pattern"; then
            echo "Error: 文件 $file 包含潜在的敏感信息(匹配模式: $pattern)"
            echo "请移除敏感信息后重试,或者使用 git reset 取消暂存"
            exit 1
        fi
    done
done
exit 0

使用专门的工具(更推荐)

使用 gitleaks 工具

# .gitleaks.toml 配置文件
[whitelist]
  files = [
    ".gitignore",
    "*.md",
    "*.test.js"
  ]
  regexes = [
    "^.*fake.*password.*$",
    "^.*example.*key.*$"
  ]
#!/bin/bash
# .git/hooks/pre-commit - 集成 gitleaks
# 检查是否安装了 gitleaks
if ! command -v gitleaks &> /dev/null; then
    echo "警告: 未安装 gitleaks,跳过密钥检测"
    exit 0
fi
# 运行 gitleaks 检测暂存区
if ! gitleaks detect --staged --verbose --config .gitleaks.toml; then
    echo "错误: 检测到潜在密钥/密码泄露,请修复后重新提交"
    exit 1
fi
exit 0

文件类型与大小限制

#!/bin/bash
# .git/hooks/pre-commit - 限制文件类型和大小
MAX_SIZE_MB=50
FORBIDDEN_FILES=(
    "*.exe"
    "*.dll"
    "*.so"
    "*.dmg"
    "*.pkg"
    "node_modules/"
    "vendor/"
)
# 检查文件大小
files=$(git diff --cached --name-only --diff-filter=ACM)
for file in $files; do
    size=$(git diff --cached --name-only -z "$file" | xargs -0 stat -f%z 2>/dev/null || \
           git diff --cached --name-only -z "$file" | xargs -0 ls -l | awk '{print $5}')
    if [ "$size" -gt $((MAX_SIZE_MB * 1024 * 1024)) ]; then
        echo "错误: 文件 $file 大于 ${MAX_SIZE_MB}MB"
        exit 1
    fi
done
# 检查禁止文件类型
for pattern in "${FORBIDDEN_FILES[@]}"; do
    if git diff --cached --name-only | grep -qE "$pattern"; then
        echo "错误: 禁止提交 ${pattern} 类型文件"
        exit 1
    fi
done
exit 0

提交信息安全审计

commit-msg 钩子

#!/bin/bash
# .git/hooks/commit-msg
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
# 禁止在提交信息中包含敏感信息
SENSITIVE_PATTERNS=(
    "password"
    "AKIA[A-Z0-9]{16}"     # AWS Key
    "sk-[A-Za-z0-9]{32}"   # OpenAI key
)
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
    if echo "$commit_msg" | grep -qE "$pattern"; then
        echo "错误: 提交信息包含敏感内容(匹配: $pattern)"
        exit 1
    fi
done
# 检查 JIRA 等工单号格式
JIRA_REGEX="^(feat|fix|chore)\([A-Z]+-[0-9]+\): "
if ! echo "$commit_msg" | grep -qE "$JIRA_REGEX"; then
    echo "警告: 提交信息格式不符合规范(期望: feat(JIRA-123): 描述)"
fi
exit 0

服务端 hook 安全策略(更严格)

pre-receive 钩子(服务端)

#!/bin/bash
# hooks/pre-receive - 服务端强制安全检查
# 读取标准输入:<old-value> <new-value> <ref-name>
while read oldrev newrev refname; do
    # 获取新提交中的文件列表
    files=$(git diff --name-only "$oldrev" "$newrev" --diff-filter=ACM)
    # 检查是否有 .env 文件被提交
    if echo "$files" | grep -qE "\.env$"; then
        echo "错误: 禁止推送 .env 文件到服务器"
        exit 1
    fi
    # 检查是否有密钥文件
    if echo "$files" | grep -qE "id_rsa|id_dsa|private.key"; then
        echo "错误: 禁止推送密钥文件"
        exit 1
    fi
    # 检查提交者身份
    for commit in $(git rev-list "$newrev" --not "$oldrev"); do
        author=$(git log -1 --format='%ae' "$commit")
        # 检查是否使用公司邮箱
        if ! echo "$author" | grep -qE "@company\.com$"; then
            echo "错误: 提交 $commit 使用非公司邮箱: $author"
            exit 1
        fi
        # 检查签名
        if ! git verify-commit "$commit" &>/dev/null; then
            echo "错误: 提交 $commit 未使用 GPG 签名"
            exit 1
        fi
    done
done
exit 0

完整的 hook 管理方案

项目级 .pre-commit-config.yaml

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: check-added-large-files
        args: ['--maxkb=500']
      - id: detect-private-key
      - id: check-merge-conflict
      - id: check-yaml
      - id: end-of-file-fixer
      - id: trailing-whitespace
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.16.3
    hooks:
      - id: gitleaks
  - repo: https://github.com/commitizen-tools/commitizen
    rev: v2.42.1
    hooks:
      - id: commitizen
        stages: [commit-msg]
  - repo: local
    hooks:
      - id: custom-security-check
        name: Custom Security Audit
        entry: scripts/security-check.sh
        language: script
        stages: [commit]

最佳实践建议

  1. 分层检查:本地 hook 做基础检查,服务端 hook 做强制审核
  2. 性能优化:只检查暂存区文件,避免全量扫描
  3. 白名单机制:允许跳过某些合法文件
  4. 工具集成:优先使用社区成熟的工具(gitleaks、truffleHog)
  5. 用户反馈:提供清晰的错误信息和修复建议
  6. 持续更新:定期更新敏感模式库
  7. 结合 CI/CD:将安全钩子集成到流水线中

通过合理配置 Git 钩子,可以在代码提交前自动拦截大多数常见的安全问题,有效降低敏感信息泄露的风险。

抱歉,评论功能暂时关闭!