A committed secret is a special kind of mistake, because git never forgets. An API key pasted into a config file and pushed once is in the history forever, even after you delete it - and in the age of AI assistants that cheerfully inline a credential to "make the example work," it happens more, not less. Gitleaks is the guard rail: a fast Go scanner that hunts your code and your entire git history for keys, tokens, and passwords before they leak.
Scan the Working Tree and the Whole History
Gitleaks can scan the files in front of you or walk every commit in the repository's history, so it catches both the secret you're about to commit and the one that slipped in six months ago:
# Scan the repo, including git history
gitleaks detect --source . --verbose
# Pre-commit: scan only staged changes
gitleaks protect --staged
# Redact the secret values in the output
gitleaks detect --source . --redact
A Pre-Commit Hook and a CI Gate
The two places Gitleaks belongs are the pre-commit hook (so a secret is caught on your machine before it's ever committed) and CI (so a pull request that carries a credential fails the build). Together they make leaking a secret something you have to actively override rather than do by accident.
Custom Rules and Allowlists
Gitleaks ships with a broad default ruleset for common providers, and a .gitleaks.toml lets you add rules for your own token formats or allowlist known-safe test fixtures to keep false positives down.
Rough Edges and Limitations
- Regex finds patterns, not intent. Expect some false positives (and tune the allowlist), and know that a truly novel secret format can slip a generic ruleset.
- History scans take time. A large, old repository's full history isn't an instant scan.
- Detection is not remediation. Finding a leaked key means you still have to rotate it - the secret in old history is already compromised.
- Command surface shifts. Flags and subcommands have evolved across major versions; check the docs for your installed release.
Add Gitleaks as a pre-commit hook once and it works silently forever, turning "we accidentally shipped a key" into a class of incident that mostly stops happening.
Internal link suggestion: link "guard rail" to the Trivy or Semgrep post to round out a security-scanning toolkit for AI-generated code.