All vulnerabilities
CRITICALSecretsexploited in the wild

SECRET-GIT-HISTORY

Secrets · Git · Secrets persisting in git history

Summary

Git is a content-addressable store: every version of every file is saved as an immutable blob object referenced by commits, so deleting a secret in a later commit or removing the file entirely leaves the original blob intact and fully reachable in history. Anyone who clones or forks the repository receives the complete object database and can recover the credential by walking old commits (git log -p, git rev-list, or extracting the blob by its hash), which is why a secret 'removed' in HEAD is still public. Truly purging it requires rewriting history with git filter-repo or the BFG Repo-Cleaner to drop the blob and force-pushing, but GitHub warns that existing clones, forks, pull-request references, and cached commit views may still expose it. GitHub's own guidance is explicit: once a secret has been pushed, consider it compromised and rotate it, because rewriting history cannot guarantee no one already copied it. Rotation is the only reliable remediation; history rewriting is cleanup, not a fix.

How to avoid it in your code

  • Rotate or revoke any secret that ever reached a remote; assume it is already compromised.
  • Rewrite history with git filter-repo or BFG Repo-Cleaner to purge the blob, then force-push.
  • Run git garbage collection and request cache/fork purging from the host after rewriting.
  • Scan full history (not just HEAD) with Trufflehog or Gitleaks to find embedded secrets.
  • Enable push protection and pre-commit hooks so secrets never enter history in the first place.

References

Related vulnerabilities

All Secrets →