Every credential you've ever committed is still in your git history — including the ones you "deleted" in the very next commit. Gitleaks is the open-source scanner that walks that history and surfaces them: fast, comprehensive, and the de facto standard for the job. Here's how to get the most out of it.
How gitleaks works
Gitleaks walks the git object store — every commit, every file, every change — and applies a set of regular expression rules to detect credential patterns. Rules are defined in a TOML configuration file and cover:
- Cloud provider credentials (AWS, GCP, Azure, DigitalOcean, Linode)
- Version control tokens (GitHub, GitLab, Bitbucket PATs)
- Payment processors (Stripe, Square, PayPal keys)
- Communication APIs (Twilio, SendGrid, Slack, Discord tokens)
- Database connection strings (PostgreSQL, MySQL, MongoDB, Redis with embedded passwords)
- Cryptographic material (RSA private keys, PEM certificates, SSH keys)
- Generic high-entropy strings that match key patterns
The default ruleset covers a broad range of credential types. Enterprise gitleaks builds add rule verification (actually calling the credential to check if it's valid) to reduce false positives.
Scanning modes
Repository scan
gitleaks detect --source . --report-format json --report-path findings.json
Scans the entire local repository history. Useful for initial baseline — run this against all your repositories before doing anything else.
Pre-commit hook
gitleaks protect --staged
Scans only the staged files before a commit. Fastest feedback — the developer knows about the issue before the commit even happens.
PR diff scanning
Scan only the commits in a PR branch relative to the base branch:
gitleaks detect --source . --log-opts="origin/main..HEAD"
BattleTest runs secret scanning against every PR diff automatically — focused on the commits introduced by the branch, keeping the scan fast and relevant.
Writing custom rules
Your internal tooling may have credential formats that aren't in the default ruleset. Add them to your .gitleaks.toml:
[[rules]]
description = "Internal API Key"
id = "internal-api-key"
regex = '''MYAPP_[A-Z0-9]{32}'''
tags = ["internal"]
[rules.allowlist]
description = "Test fixtures"
paths = ['''test/fixtures/.*''']
Handling false positives
Not every match is a real credential. Common false positives:
- Test fixtures with fake-looking-but-valid-format keys
- Documentation examples
- Hash values that match the entropy pattern
- Base64-encoded non-secret data
Suppress false positives with an allowlist in .gitleaks.toml:
[allowlist]
description = "Global allowlist"
paths = [
'''test/''',
'''docs/''',
]
commits = [
"abc123def456" # known false positive commit
]
regexes = [
'''(?i)example|placeholder|fake'''
]
What happens when you find a real secret
Act immediately:
- Revoke the credential (assume it's already compromised if it was in any public repo or accessible private repo)
- Check the access logs for the service the credential accesses — look for unauthorised API calls
- Generate a new credential and update all references
- Use
git filter-branchor BFG Repo Cleaner to remove it from history, then force-push — this doesn't help people who already cloned, but it stops future clones from having it - Add the commit hash to your gitleaks allowlist so it stops alerting on the now-removed commit
Integrating gitleaks with BattleTest
BattleTest runs secret scanning against every PR diff automatically. Findings are surfaced in the PR review comment alongside other security findings. No separate GitHub Actions workflow to configure — it's part of the default security review.
For teams that also want the pre-commit protection on developer workstations, the gitleaks pre-commit hook can run independently of BattleTest — they complement each other rather than duplicate.