关于 git-security-2025
面向开发者的 Git 安全实践指南,涵盖零信任、签名提交、密钥扫描和审计,提供配置示例与事件处置步骤。
主要功能
- 01零信任 Git 安全原则
- 02GPG 与 SSH 提交签名
- 03密钥扫描与防护
- 04分支保护与审计
- 05泄露事件处置指南
适用场景
- 01为仓库制定签名提交要求
- 02在提交前扫描密钥
- 03配置分支保护与持续审计
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ josiahsiegel/ claude-plugin-marketplace --skill git-security-2025安装后在 Claude Code 中输入/git-security-2025确认已加载。
附带文件references/credential-and-code-scanning.md
详细介绍
🚨 关键指南
Windows 文件路径要求
强制要求:在 Windows 上始终使用反斜杠表示文件路径
在 Windows 上使用 Edit 或 Write 工具时,文件路径必须使用反斜杠(\),不得使用正斜杠(/)。
示例:
- ❌ 错误:
D:/repos/project/file.tsx - ✅ 正确:
D:\repos\project\file.tsx
适用于:
- Edit 工具的 file_path 参数
- Write 工具的 file_path 参数
- Windows 系统上的所有文件操作
文档指南
除非用户明确要求,否则绝不创建新的文档文件。
- 优先事项:更新现有的 README.md 文件,而不是创建新文档
- 保持仓库整洁:保持仓库根目录整洁——除非用户另有要求,否则仅保留 README.md
- 风格:文档应简洁、直接、专业——避免使用 AI 生成的语气
- 用户偏好:仅在用户明确要求提供文档时,才创建其他 .md 文件
Git 安全最佳实践 2025
零信任安全模型(2025 年标准)
定义: 必须对每位开发者的身份进行明确的身份验证和授权。所有 Git 操作都要记录、签名并持续监控。
核心原则:
- 永不信任,始终验证——验证每次提交
- 最小权限访问——仅授予所需的最低权限
- 持续监控——记录并审计所有操作
- 假定已遭入侵——采取纵深防御策略
在 Git 中实施零信任
1. 强制签名提交:
# Global requirement
git config --global commit.gpgsign true
git config --global tag.gpgsign true
# Enforce via branch protection (GitHub/GitLab/Azure DevOps)
# Repository Settings → Branches → Require signed commits
2. 身份验证:
# Every commit must verify identity
git log --show-signature -10
# Reject unsigned commits in CI/CD
# .github/workflows/verify.yml
- name: Verify all commits are signed
run: |
git log --pretty="%H" origin/main..HEAD | while read commit; do
if ! git verify-commit "$commit" 2>/dev/null; then
echo "ERROR: Unsigned commit $commit"
exit 1
fi
done
3. 持续审计日志记录:
# Enable Git audit trail
git config --global alias.audit 'log --all --pretty="%H|%an|%ae|%ad|%s|%GK" --date=iso'
# Export audit log
git audit > git-audit.log
# Monitor for suspicious activity
git log --author="*" --since="24 hours ago" --pretty=format:"%an %ae %s"
4. 最小权限访问:
# GitHub branch protection (zero-trust model)
branches:
main:
protection_rules:
required_pull_request_reviews: true
dismiss_stale_reviews: true
require_code_owner_reviews: true
required_approving_review_count: 2
require_signed_commits: true
enforce_admins: true
restrictions:
users: [] # No direct push
teams: ["security-team"]
5. 持续监控:
# Monitor all repository changes
# .github/workflows/security-monitor.yml
name: Security Monitoring
on: [push, pull_request]
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for unsigned commits
run: git verify-commit HEAD || echo "::warning::Unsigned commit detected"
- name: Scan for secrets
run: gitleaks detect --exit-code 1
- name: Check commit author
run: |
AUTHOR=$(git log -1 --format='%an <%ae>')
echo "Commit by: $AUTHOR"
# Log to SIEM/security monitoring
签名提交(2025 年强制要求)
原因: 通过加密方式验证提交者身份,防止冒名顶替,并确保审计跟踪。
行业趋势: 2025 年的工作流中,签名提交正日益成为强制要求。
GPG 签名(传统方式)
设置:
# Generate GPG key
gpg --full-generate-key
# Choose: RSA and RSA, 4096 bits, expires in 2y
# List keys
gpg --list-secret-keys --keyid-format=long
# Example output:
# sec rsa4096/ABC123DEF456 2025-01-15 [SC] [expires: 2027-01-15]
# uid [ultimate] Your Name <[email protected]>
# ssb rsa4096/GHI789JKL012 2025-01-15 [E] [expires: 2027-01-15]
# Configure Git
git config --global user.signingkey ABC123DEF456
git config --global commit.gpgsign true
git config --global tag.gpgsign true
# Export public key for GitHub/GitLab
gpg --armor --export ABC123DEF456
# Copy output and add to GitHub/GitLab/Bitbucket
# Sign commits
git commit -S -m "feat: add authentication"
# Verify signatures
git log --show-signature
git verify-commit HEAD
git verify-tag v1.0.0
故障排除:
# GPG agent not running
export GPG_TTY=$(tty)
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc
# Cache passphrase longer
echo 'default-cache-ttl 34560000' >> ~/.gnupg/gpg-agent.conf
echo 'max-cache-ttl 34560000' >> ~/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye
# Test signing
echo "test" | gpg --clearsign
SSH 签名(现代替代方案 - 2023 年及以后)
使用 SSH 的原因: 更简单,可重复使用现有 SSH 密钥,无需 GPG。
设置:
# Check if SSH key exists
ls -la ~/.ssh/id_ed25519.pub
# Generate if needed
ssh-keygen -t ed25519 -C "[email protected]"
# Configure Git to use SSH signing
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
# Add public key to GitHub
cat ~/.ssh/id_ed25519.pub
# GitHub Settings → SSH and GPG keys → New SSH key → Key type: Signing Key
# Sign commits (automatic with commit.gpgsign=true)
git commit -m "feat: add feature"
# Verify
git log --show-signature
配置允许的签名者文件(用于验证):
# Create allowed signers file
echo "[email protected] $(cat ~/.ssh/id_ed25519.pub)" > ~/.ssh/allowed_signers
# Configure Git
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
# Verify commits
git verify-commit HEAD
密钥扫描与预防
GitHub 密钥扫描(推送保护)
在仓库中启用:
- Settings → Code security → Secret scanning → 启用
- 启用推送保护(在推送时拦截密钥)
AI 驱动的检测(2025 年):
- AWS 凭证
- Azure 服务主体
- Google Cloud 密钥
- GitHub 令牌
- 数据库连接字符串
- API 密钥(OpenAI、Stripe、Anthropic 等)
- 私钥
- OAuth 令牌
- 自定义模式
推送被拦截示例:
$ git push
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote:
remote: - Push cannot contain secrets
remote:
remote: Resolve the following violations before pushing again
remote:
remote: -- AWS Access Key
remote: locations:
remote: - config.py:12
remote:
remote: (Disable push protection: https://github.com/settings/security_analysis)
remote:
To github.com:user/repo.git
! [remote rejected] main -> main (push declined due to repository rule violations)
修复方法:
# Remove secret from file
# Use environment variable instead
echo "AWS_ACCESS_KEY=your_key" >> .env
echo ".env" >> .gitignore
# Remove from history if already committed
git rm --cached config.py
git commit -m "Remove secrets"
# If in history, use filter-repo
git filter-repo --path config.py --invert-paths
git push --force
Gitleaks(本地扫描)
安装:
# macOS
brew install gitleaks
# Linux
wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.0/gitleaks_8.18.0_linux_x64.tar.gz
tar -xzf gitleaks_8.18.0_linux_x64.tar.gz
sudo mv gitleaks /usr/local/bin/
# Windows
choco install gitleaks
用法:
# Scan entire repository
gitleaks detect
# Scan uncommitted changes
gitleaks protect
# Scan specific directory
gitleaks detect --source ./src
# Generate report
gitleaks detect --report-format json --report-path gitleaks-report.json
# Use in CI/CD
gitleaks detect --exit-code 1
提交前钩子:
# .git/hooks/pre-commit
#!/bin/bash
gitleaks protect --staged --verbose
if [ $? -ne 0 ]; then
echo "⚠️ Gitleaks detected secrets. Commit blocked."
exit 1
fi
Git-secrets(面向 AWS)
# Install
brew install git-secrets # macOS
# or
git clone https://github.com/awslabs/git-secrets.git
cd git-secrets
sudo make install
# Initialize in repository
git secrets --install
git secrets --register-aws
# Add custom patterns
git secrets --add 'password\s*=\s*[^\s]+'
git secrets --add 'api[_-]?key\s*=\s*[^\s]+'
# Scan
git secrets --scan
git secrets --scan-history
强制签名提交
分支保护规则
GitHub:
Repository → Settings → Branches → Branch protection rules
☑ Require signed commits
☑ Require linear history
☑ Require status checks to pass
GitLab:
Repository → Settings → Repository → Protected branches
☑ Allowed to push: No one
☑ Allowed to merge: Maintainers
☑ Require all commits be signed
Azure DevOps:
Branch Policies → Add policy → Require signed commits
预接收钩子(服务端强制执行)
#!/bin/bash
# .git/hooks/pre-receive (on server)
zero_commit="0000000000000000000000000000000000000000"
while read oldrev newrev refname; do
# Skip branch deletion
if [ "$newrev" = "$zero_commit" ]; then
continue
fi
# Check all commits in push
for commit in $(git rev-list "$oldrev".."$newrev"); do
# Verify commit signature
if ! git verify-commit "$commit" 2>/dev/null; then
echo "Error: Commit $commit is not signed"
echo "All commits must be signed. Configure with:"
echo " git config commit.gpgsign true"
exit 1
fi
done
done
exit 0
安全配置
推荐的 Git 配置
# Enforce signed commits
git config --global commit.gpgsign true
git config --global tag.gpgsign true
# Use SSH signing (modern)
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
# Security settings
git config --global protocol.version 2
git config --global transfer.fsckobjects true
git config --global fetch.fsckobjects true
git config --global receive.fsckobjects true
# Prevent credential leaks
git config --global credential.helper cache --timeout=3600
# Or use system credential manager
git config --global credential.helper wincred # Windows
git config --global credential.helper osxkeychain # macOS
# Line ending safety
git config --global core.autocrlf true # Windows
git config --global core.autocrlf input # macOS/Linux
# Editor safety (avoid nano/vim leaks)
git config --global core.editor "code --wait"
.gitignore 安全性
# Secrets
.env
.env.*
*.pem
*.key
*.p12
*.pfx
*_rsa
*_dsa
*_ecdsa
*_ed25519
credentials.json
secrets.yaml
config/secrets.yml
# Cloud provider
.aws/
.azure/
.gcloud/
gcloud-service-key.json
# Databases
*.sqlite
*.db
# Logs (may contain sensitive data)
*.log
logs/
# IDE secrets
.vscode/settings.json
.idea/workspace.xml
# Build artifacts (may contain embedded secrets)
dist/
build/
node_modules/
vendor/
凭证管理与 CodeQL 扫描
有关凭证管理(PAT、SSH 密钥、Git Credential Manager、轮换和存储)以及 CodeQL / 安全扫描设置的详细指南,请参阅 references/credential-and-code-scanning.md。在加强开发者凭证安全或添加仓库级静态安全分析时,请加载该参考文档。
审计跟踪
启用详细日志记录
# Log all Git operations
git config --global alias.ll 'log --all --graph --decorate --oneline --show-signature'
# Check commit verification
git log --show-signature -10
# Export audit log
git log --pretty=format:"%H,%an,%ae,%ad,%s" --date=iso > git-audit.csv
# Verify all commits in branch
git log --show-signature main..HEAD
安全检查清单
仓库设置:
- ☑ 启用分支保护
- ☑ 要求提交签名
- ☑ 启用带推送保护的密钥扫描
- ☑ 启用 CodeQL 或类似扫描
- ☑ 配置 Dependabot/Renovate
- ☑ 要求所有贡献者启用 2FA
开发者工作站:
- ☑ 使用 GPG 或 SSH 提交签名
- ☑ 配置凭据管理器(绝不使用明文)
- ☑ 安装并配置 gitleaks
- ☑ 创建完善的 .gitignore
- ☑ 为传输启用 fsckobjects
- ☑ 使用带密码短语的 SSH 密钥
工作流:
- ☑ 绝不提交密钥
- ☑ 提交前检查变更
- ☑ 在拉取/合并时验证签名
- ☑ 定期进行安全审计
- ☑ 定期轮换凭据
- ☑ 使用环境变量存储密钥
事件响应
提交中泄露了密钥:
# 1. Rotate compromised credentials IMMEDIATELY
# 2. Remove from latest commit (if not pushed)
git reset HEAD~1
# Edit files to remove secret
git add .
git commit -m "Remove secrets"
# 3. If pushed, remove from history
git filter-repo --path config/secrets.yml --invert-paths
git push --force
# 4. Notify team to re-clone
# 5. Enable push protection to prevent future leaks
检测到未签名的提交:
# Identify unsigned commits
git log --show-signature | grep "No signature"
# Re-sign commits (if you authored them)
git rebase --exec 'git commit --amend --no-edit -n -S' -i HEAD~10
# Force push (with team coordination)
git push --force-with-lease