Secret Committed to Git: Rotate, Purge, Prevent
Fast recall
Quick revision
Core answer
git filter-repo or BFG, then force-push (every collaborator must re-clone); (4) prevent recurrence: pre-commit hooks (gitleaks, trufflehog), GitHub Push Protection, OIDC instead of static credentials.Understanding that git history rewrites don't undo a leak — rotation is the only real fix
Trying to `git revert` the commit and thinking the secret is gone — the secret is still in history; revert just adds a new commit
Discuss why force-push to public history is irreversible (clones, forks, GitHub events, search indexes), and OIDC as the structural fix
Interview-ready guide
Interview answer
Once a secret is pushed to GitHub, it's compromised — secret-scanning bots monitor public repos and the GitHub Events API in real time, indexing new commits within seconds. Even on private repos, the credential may be cached by GitHub's UI, backed up by integrations, or seen by collaborators. The instinct to "clean it up first" before rotating is wrong; rotation is the only real mitigation.
The correct order
Step 1 — rotate within 5 minutes
- AWS:
aws iam update-access-key --status Inactive, then create a new one; deactivate before deleting in case an internal system was using it legitimately - Other credentials: GitHub PAT regenerate, Vault token revoke, Stripe key deactivate
Step 2 — audit CloudTrail within 30 minutes
- Query for use of the leaked key ID; look at every API call made with it
- Watch for IAM modifications, unusual regions, data egress — classic post-compromise patterns where attackers escalate before being detected
- If anything suspicious, escalate to security incident response
Step 3 — purge from git history
- Use
git filter-repo(recommended, replaces deprecated filter-branch) or BFG Repo-Cleaner to rewrite history removing the secret - Force-push all branches and tags; notify all collaborators to delete local clones and re-clone fresh
- Be honest about limits: GitHub may retain the old commit accessible by SHA for some time; forks of the repo still contain the secret; the Events API already broadcast the push; anyone who cloned during the leak window has it locally
Step 4 — prevent recurrence with layered defense
- Pre-commit hook on every developer machine: gitleaks via pre-commit framework; commit aborts if a secret is detected
- CI scanning catches what dev hooks missed (developer disabled hooks, new contributor without setup)
- GitHub Push Protection blocks pushes containing detected secrets (AWS keys, Stripe keys, GitHub tokens)
- Structural fix: migrate to OIDC — GitHub Actions can federate to AWS without storing any long-lived secret in repo or org; the safest secret is the one that doesn't exist
The confusion to clear up
git revertdoes NOT remove the secret; revert creates a new commit that undoes changes; the original commit with the secret is still in history- Only history rewrite (filter-repo, BFG) actually removes the secret from history
- Even after rewrite, the secret is leaked to anyone who saw it in the rewrite window
The cultural piece
- Blameless reporting matters — an engineer who admits the leak immediately enables fast rotation; punitive cultures delay reporting, which extends exposure
- Make secret-scanning automatic, not optional — pre-commit installation should be part of repo bootstrap so new contributors get protected by default
The strategic answer is OIDC
- Long-lived secrets in CI are an inherent risk — they leak in logs, sit in repo configs, sprawl across systems
- OIDC eliminates long-lived secrets entirely; tokens are short-lived and request-scoped via repo and branch claims
- Pre-commit hooks are tactical; OIDC migration is the strategic structural fix every team should be on the path to
Secret Committed to Git: Rotate, Purge, Prevent
Direct Answer
Treat as compromised the moment it hits the remote: (1) rotate the credential immediately (deactivate then create new) — invalidating the leaked value is the only real mitigation; (2) audit usage via CloudTrail/Audit Logs for unauthorized API calls; (3) purge from history with git filter-repo or BFG, then force-push (every collaborator must re-clone); (4) prevent recurrence: pre-commit hooks (gitleaks, trufflehog), GitHub Push Protection, OIDC instead of static credentials.
Common Mistakes & Pitfalls
Trying to git revert the commit and thinking the secret is gone — the secret is still in history; revert just adds a new commit
Check your understanding
Answer these without looking back at the article.
- Why is `git filter-repo` preferred over `git filter-branch`?
- How does GitHub Push Protection work and what does it block?
- What is OIDC federation between GitHub Actions and AWS?
- How do you handle a secret leaked to a public repo with hundreds of forks?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.