Setting Up Gitleaks: Prevent API Key and Password Leaks from Git Hooks to CI/CD Pipelines

Git tutorial - IT technology blog
Git tutorial - IT technology blog

The Problem: One Careless Enter, and Your AWS Token Is Public on GitHub

Most developers know that sinking feeling in their chest right after running git push with an OpenAI API key or AWS secret access key accidentally left in a commit. It takes automated bots on the Internet anywhere from two to five minutes to scrape freshly exposed tokens. The next morning, you wake up to a $5,000 AWS bill run up by cryptominers—or discover your entire customer database has been dumped.

The root cause is almost always mundane: hardcoding credentials for a quick test and forgetting to delete them, or carelessly running git add . and packaging your .env file into the commit. Relying purely on human vigilance is never a safe security strategy. You need automated secret scanning operating at two distinct checkpoints: locally on the developer’s machine (Git hooks) and remotely on your test pipeline (CI/CD). That is precisely where Gitleaks comes in.

1. Quick Start: Install and Run Your First Scan in 3 Minutes

Gitleaks is a standalone Go binary with a startup time of just a few milliseconds. It combines regular expressions with the Shannon Entropy algorithm to detect credentials across more than 160 popular services.

Step 1: Install Gitleaks

On macOS, the fastest installation method is via Homebrew:

brew install gitleaks

On Linux, download the pre-built binary directly:

wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.2/gitleaks_8.18.2_linux_x64.tar.gz
tar -zxvf gitleaks_8.18.2_linux_x64.tar.gz
sudo mv gitleaks /usr/local/bin/

Verify that the binary is available in your PATH:

gitleaks version

Step 2: Test-Scan Your Repository

From the root directory of your project, scan the entire commit history from day one:

gitleaks detect --verbose

If you only want to inspect files currently staged with git add:

gitleaks protect --staged --verbose

If a secret is caught, the terminal will instantly highlight the filename, line number, fingerprint, and secret type (e.g., Stripe Secret Key, AWS Access Key) in red, terminating with exit code 1 to abort the operation.

2. How It Works and Setting Up Two-Layer Defense

How Does Gitleaks Analyze Source Code?

Gitleaks’ TOML configuration file operates on two primary mechanisms:

  • Regex Patterns: Matches strings with clear, structured formats. For example, AWS Access Key IDs consistently start with the prefix AKIA[0-9A-Z]{16}, while GitHub tokens follow the pattern ghp_[a-zA-Z0-9]{36}.
  • Shannon Entropy: Calculates the randomness of a string. A 32-character random password like xK9#mQ2$vL8!zP1@ exhibits extremely high entropy, distinguishing it from conventional identifiers like user_display_name.

Checkpoint 1: Git Pre-Commit Hook on the Local Machine

Stop secrets right on your local machine before they ever get baked into a commit hash. If a token is detected, the commit will be rejected immediately.

Using the pre-commit framework is the cleanest approach, though teams often integrate scanner checks alongside tools like Lefthook for Git hooks management or Husky and lint-staged. Create a .pre-commit-config.yaml file at the root of your repository:

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

Install the hook into your project’s .git/hooks directory:

pip install pre-commit
pre-commit install

Once this is configured, whenever you run git commit, the hook automatically inspects staged files. If any secret is found, the commit is stopped in its tracks.

Checkpoint 2: The CI/CD Pipeline Gatekeeper

Why do you still need CI/CD? Because developers can easily bypass local hooks using git commit --no-verify. The CI/CD server acts as the ultimate authority: code cannot be merged unless it passes the scan.

Here is a sample workflow file for GitHub Actions (.github/workflows/gitleaks.yml):

name: gitleaks-security-scan

on:
  pull_request:
    branches: [ main, develop ]
  push:
    branches: [ main ]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Important Note: You must explicitly specify fetch-depth: 0. By default, GitHub Actions fetches only the single latest commit, causing the runner to miss all intermediate commits within a Pull Request.

3. Advanced: Custom Rules and Managing False Positives

Customization via .gitleaks.toml

Projects frequently include mock test data or internal tokens that trigger false positives in Gitleaks. If you also need to manage local configuration overrides, techniques like assume-unchanged vs. skip-worktree can help keep sensitive settings from ever being tracked. Create a .gitleaks.toml file in your root directory to exclude specific paths:

title = "Custom Gitleaks Config"

[extend]
useDefault = true

[allowlist]
description = "Ignore fixtures and lockfiles"
paths = [
  '''tests/fixtures/.*''',
  '''go\.sum''',
  '''package-lock\.json'''
]
regexes = [
  '''fake_dummy_secret_for_unit_tests'''
]

Quick Whitelisting with Inline Comments

When writing unit tests for payment gateways, including a mock key in test files is often inevitable. Instead of writing complex global rules, simply append this inline comment to the end of the line:

stripe_test_key = "pk_test_51NzABC1234567890dummy"  # gitleaks:allow

The scanner will ignore that line.

4. Battle-Tested Lessons from Team Deployments

Setting up the tool takes just 15 minutes, but introducing it to day-to-day operations can surface team culture hurdles. Here are three key lessons learned from implementing it across teams:

  • Deleting a secret and committing over it does not fix the issue: The secret remains fully accessible in your Git log history. Step 1: Immediately revoke and rotate the compromised credential in your provider’s console. Step 2: Use git-filter-repo or BFG Repo-Cleaner to completely purge that commit from your Git history.
  • Create a baseline for legacy repositories: Enabling Gitleaks on a 5-year-old repository might trigger hundreds of historical alerts all at once. Run gitleaks detect --report-path baseline.json to capture existing legacy warnings. Then pass the --baseline-path flag in your CI/CD configuration so that it only blocks newly introduced commits moving forward.
  • Set safe conventions for .env.example files: Never include long, random strings in template files. Always use clear, explicit placeholders such as STRIPE_KEY=your_stripe_key_here to avoid tripping the entropy detector.
Share: