饮墨

子安饮墨馀三斗,留与卿儿作赋来

Gitleaks 代码仓库密钥泄漏检测实战:3 步构建从本地到 CI/CD 的 Secrets 防线

5 views

痛点:密钥泄漏,运维最怕的"低级错误"

你有没有经历过这样的场景:某天安全团队突然告警,说公司的 AWS Access Key 出现在了 GitHub 公开仓库里。一查提交记录,是某位同事三个月前不小心把 .env 文件提交了上去。虽然后来删除了文件,但 git log 里白纸黑字,密钥早已被扫描机器人抓取。

这不是个案。GitGuardian 的年度报告显示,仅公开仓库每年就有超过 1200 万条密钥泄漏。更可怕的是内部仓库——没有外部审计,泄漏往往数月甚至数年无人发现。

传统做法是靠 .gitignore 和口头规范,但人总会犯错。我们需要的是自动化检测机制,在密钥进入 Git 历史之前拦截它。

Gitleaks 就是干这事的——一个轻量、快速、开源的 Git 仓库密钥扫描工具,支持 pre-commit 本地拦截和 CI/CD 流水线集成。

方案:Gitleaks 三层防线架构

开发者本地 (pre-commit) → CI/CD Pipeline (GitHub Actions/GitLab CI) → 定期全量扫描 (cron)
         ↓ 拦截                    ↓ 阻断                           ↓ 兜底

核心思路:左移检测 + 纵深防御。本地 hook 拦截 90% 的意外提交,CI/CD 作为第二道门,定期全量扫描兜底历史遗留问题。

实操步骤

第 1 步:安装 Gitleaks 并扫描现有仓库

# macOS
brew install gitleaks

# Linux(下载二进制,以 v8.21.2 为例)
wget https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz
tar -xzf gitleaks_8.21.2_linux_x64.tar.gz
sudo mv gitleaks /usr/local/bin/

# 验证安装
gitleaks version

先对现有仓库做一次全量扫描,摸清家底:

# 扫描整个 Git 历史(检测所有已提交内容)
cd /path/to/your-repo
gitleaks detect --source . -v

# 仅扫描工作目录(未提交的文件)
gitleaks protect --source . -v

# 输出 JSON 报告,便于后续处理
gitleaks detect --source . --report-format json --report-path gitleaks-report.json

Gitleaks 内置了 150+ 条规则,覆盖 AWS、GCP、Azure、GitHub Token、Slack Webhook、数据库连接串、私钥等常见密钥类型。扫描速度极快,万级 commit 的仓库通常在 10 秒内完成。

第 2 步:配置 pre-commit Hook,本地拦截

用 pre-commit 框架集成 Gitleaks,让每次 git commit 自动检测:

# 安装 pre-commit
pip install pre-commit

在仓库根目录创建 .pre-commit-config.yaml:

repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.21.2
    hooks:
      - id: gitleaks

激活 hook:

pre-commit install

从此每次 git commit 都会自动扫描暂存区。如果检测到密钥,提交直接被阻断:

Gitleaks...............................................................Failed
- hook id: gitleaks
- exit code: 1

○
    │╲
    │ │
    ○ ○

Finding:     AKIAIOSFODNN7EXAMPLE
Secret:      AKIAIOSFODNN7EXAMPLE
RuleID:      aws-access-key-id
File:        config/settings.py
Line:        42
Commit:      (staged)

开发者必须移除密钥后才能提交——问题在源头就被掐灭。

第 3 步:CI/CD 流水线集成,双重保障

本地 hook 可以被 --no-verify 跳过,所以 CI/CD 层的检测必不可少。

GitHub Actions 示例:

# .github/workflows/gitleaks.yml
name: Gitleaks Secret Scan
on: [push, pull_request]

jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 必须全量拉取,否则无法扫描历史

      - name: Run Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

GitLab CI 示例:

# .gitlab-ci.yml
gitleaks:
  stage: test
  image: zricethezav/gitleaks:latest
  script:
    - gitleaks detect --source . --log-opts="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" -v
  allow_failure: false

PR/MR 中发现密钥直接标红阻断,强制开发者修复后才能合入。

3 个常见坑与解决方案

坑 1:误报太多,团队抵触

Gitleaks 默认规则可能对测试用的 mock key、文档中的示例密钥产生误报。解决方法是在仓库根目录创建 .gitleaksignore 文件:

# .gitleaksignore — 每行一个 fingerprint(从扫描报告中获取)
3b5a7b8c9d2e1f0a...
a1b2c3d4e5f6789...

也可以在代码行尾加注释标记忽略:

API_KEY = "test-key-not-real"  # gitleaks:allow

坑 2:扫描到历史泄漏,但密钥已轮换

历史中的密钥即使已轮换,也建议记录并加入 .gitleaksignore。如果需要从历史中彻底清除,用 git filter-repo:

# 安装
pip install git-filter-repo

# 从所有历史中删除包含密钥的文件
git filter-repo --path secrets.env --invert-paths

注意: 这会重写 Git 历史,团队所有人需要重新 clone。仅在必要时使用。

坑 3:自定义密钥格式漏检

公司内部的 Token 格式(如 mycompany_sk_live_xxxx)默认规则不覆盖。创建 .gitleaks.toml 自定义规则:

# .gitleaks.toml
[[rules]]
id = "mycompany-secret-key"
description = "MyCompany Secret Key"
regex = '''mycompany_sk_(live|test)_[a-zA-Z0-9]{32,}'''
tags = ["key", "mycompany"]

总结

防线层级 工具 效果
本地 pre-commit Gitleaks hook 提交前拦截,开发者即时修复
CI/CD Pipeline Gitleaks Action PR/MR 阻断,防止绕过本地检查
定期全量扫描 Gitleaks cron 兜底历史遗留,持续审计

密钥泄漏是可预防的安全事故。Gitleaks 安装简单、零侵入、扫描极快,三步就能建立从开发到部署的完整防线。别等安全团队来找你——今天就在仓库里加上这道锁。

分享:

相关文章