Back to blog
technicalsupply chainguide

Secrets in Git: the API key you deleted is still there

Published on 2026-07-066 min readCleanIssue

"We deleted it two years ago"

A real audit scenario: an AWS key committed in a .env file in 2023, "deleted" three days later by a remove secrets commit. In 2026, it's still valid, still present in the Git history, and available to anyone who clones the repository.

Git is designed to forget nothing. A git rm creates a new commit *on top* — the file remains in every previous commit, recoverable with a single command.

How attackers find your keys

On public repositories: within minutes

Bots continuously scan public GitHub and GitLab commits for key patterns (AWS, Stripe, OpenAI, Supabase, npm tokens…). The delay between pushing a public AWS key and its first malicious use is measured in minutes. GitHub's secret scanning auto-revokes some of them, but covers neither every format nor every provider.

On private repositories: via secondary access

"Our repo is private" only protects you as long as it stays that way. Leaks happen through: a compromised developer laptop, an over-permissive CI/CD token, a contractor whose access was never revoked, a repo re-published as public years later. The full history leaves with the clone.

The 2026 case: AI-generated projects

Applications built with code-generation tools are over-represented in our findings: hardcoded keys "just for testing" suggested by the assistant, then committed along with everything else. If you vibe-coded your MVP, your repository history deserves an inspection.

What to do, in the right order

The classic mistake is starting by rewriting history. No:

  • Revoke first. Any key present in the history must be considered compromised and regenerated immediately. It's the only step that neutralizes the risk.
  • Check for usage. Review the provider's logs (CloudTrail for AWS, the Stripe dashboard…) to detect fraudulent use during the exposure window.
  • Clean the history with git filter-repo — good hygiene, but useless for security if the key isn't revoked, and insufficient anyway: forks, local clones and CI caches keep the old version.
  • Prevent recurrence: a pre-commit hook with a secret scanner (gitleaks, trufflehog), scanning in CI, and secrets injected at runtime rather than stored in files.
  • Checklist

  • [ ] Scan the full history of all your repositories (gitleaks git .), not just HEAD
  • [ ] Revoke and regenerate every secret found, even "old" ones
  • [ ] Pre-commit hook + CI scan on all repositories
  • [ ] .env* in the .gitignore of your project templates
  • [ ] Scheduled rotation of critical keys (rotation limits the exploitation window of any future leak)
  • [ ] Repository access reviewed: former contractors, CI tokens, third-party OAuth apps
  • Our First Review includes a search for exposed secrets tied to your product — repositories, JavaScript bundles, public histories. 48h to know what's out there.

    Related articles

    Three adjacent analyses to keep exploring the same attack surface.

    Sources

    Written by CleanIssue
    Reviewed on 2026-07-06

    Related services

    If this topic maps to a real risk in your stack, these are the most relevant CleanIssue audits.

    Need an external review of your HR SaaS?

    Share your product, stack, and client context. We will come back with the right review scope.

    Discuss your audit