Secrets in git history: finding, rotating and preventing leaks
A leaked API key is the cheapest breach there is: no exploit chain, no privilege escalation, just a valid credential in a place it should not be. Most teams handle the first 20 minutes wrong, which is what turns a leak into an incident.
Removing the line does not remove the secret
Git keeps every object it has ever tracked. A commit that deletes the credential leaves the previous blob reachable through history, forks, clones, pull-request refs and CI caches. If the repository was ever public or shared, assume the value is compromised.
The correct response order
Rotation comes first because it is the only step that removes attacker capability. Everything else is cleanup.
- ▸1. Rotate the credential at the provider and confirm the old value fails.
- ▸2. Review provider audit logs for use of the old value.
- ▸3. Remove it from history (filter-repo or BFG) and coordinate force-push with the team.
- ▸4. Invalidate CI caches and artefacts that may embed the value.
- ▸5. Add a detection rule so the same shape of secret is caught next time.
Scanning history without drowning in noise
High-confidence detection combines a shape match with a verification step: does the candidate string authenticate against the provider? Verified findings deserve a page; unverified ones deserve a queue.
- ▸Scan the full history once to establish a baseline, then scan diffs on every push.
- ▸Prefer verified-credential checks over regex-only matches to keep precision high.
- ▸Cover config, notebooks, lockfiles, Dockerfiles, CI definitions and commit messages.
Prevention that developers accept
Pre-commit hooks catch mistakes at the cheapest moment, but they are bypassable and local — pair them with a server-side check that blocks the push or fails the pipeline. The real fix is removing the reason to paste a secret at all: short-lived credentials from a secrets manager, workload identity in CI, and no long-lived static keys in developer environments.
Frequently asked
Do I need to rewrite history if the repository is private?
Rotate first regardless. History rewriting is still worth doing for private repositories, because clones, forks and CI caches widen exposure over time.
What kinds of secrets are most often missed?
Credentials inside notebooks, CI definitions, Docker build arguments and commit messages — places code-focused scanners often skip.
Put this into practice
Start scanning your own repositories free, or download the AI/LLM security checklist to audit what you already ship.