
Here's a number that should get your attention. In its State of Secrets Sprawl 2026 report, GitGuardian found roughly 29 million new secrets โ API keys, passwords, tokens โ sitting in public GitHub repositories from 2025 alone, the largest single-year jump they've ever recorded. And the part that hits closest to home if you build with AI tools: AI-assisted commits leak secrets at about 3.2% of the time, roughly twice the baseline rate. The tools that make us all faster are also helping us ship keys before we notice.
If you've ever hardcoded an API key, committed it, then quietly deleted the line and pushed again, this article is for you โ because that delete almost certainly did not fix the problem.
Think of git not as a folder of your latest files, but as a tape recording of every change you've ever made. Every commit is a frozen snapshot. When you "delete" a secret, you're not erasing the tape โ you're just recording a new snapshot that leaves it out. The old snapshot, the one with your key in it, is still on the tape, and anyone who scrolls back can play it.
This is confirmed straight from GitHub's own documentation: deleting a file or line in a new commit does not remove the sensitive data from your repository's history. To truly remove it, you have to rewrite the entire history โ and even then, copies can survive in forks and caches.
So when you commit a key, then delete the line and push again, your key is still sitting in that first commit โ available to anyone with access to the repo. If the repo is public, that means everyone. Automated bots scan public GitHub for exposed keys within minutes of a push.
If you think this is just a beginner problem, consider what surfaced in May 2026. Researchers found a public GitHub repository tied to a contractor for the U.S. Cybersecurity and Infrastructure Security Agency (CISA) โ a personal account the contractor had been using to sync files, not an official agency repo. Inside were plaintext passwords, AWS GovCloud access tokens, and identity certificates. Two details make it worse, not better: the repository had been public for roughly six months before anyone noticed, and the exposed credentials reportedly stayed valid for hours to days after the leak was discovered โ long enough for an attacker to use them. Reporting also indicated GitHub's secret-scanning push protection had been manually turned off on the account. This was tied to the federal agency whose entire job is cybersecurity, and the keys still sat in the open for months.
The lesson isn't "ha, the experts mess up too." It's that anyone can do this, the stakes are real, and the fix is the same for all of us.
If you've leaked a key, do these three things โ in this order. The order matters more than anything else in this article.
Go to wherever the key lives โ OpenAI, Stripe, Supabase, your cloud provider โ and revoke or regenerate it. This invalidates the leaked key so it can't be used anymore, even if someone already copied it.
GitGuardian's official remediation guidance is blunt: revoking the secret "is the only way to ensure no attacker will access the involved service." And then the most freeing sentence you'll read today:
"Once you have revoked the secret, you should typically stop here. The secret is now useless to attackers, and your security incident is resolved."
Read that again. Rotation is the fix. Everything below is optional cleanup.
If you want the secret physically gone from the tape, you can rewrite history with a dedicated tool. The two that the git community and GitGuardian both recommend are BFG Repo-Cleaner (simpler and fast) and git-filter-repo (more powerful, recommended by the core git developers). Both rewrite every commit to strip the secret out.
They're not beginner-friendly, so follow each tool's official guide step by step, and don't trust random flags from a chatbot. But remember, this is secondary: a scrubbed history with a still-live key is worse than a messy history with a dead one. Rotate first.
If your provider offers usage or access logs (most do), look for unfamiliar IP addresses, spikes in usage, or activity you don't recognize. If you rotated the key quickly, you're probably fine โ but it's worth a glance.
The whole mess above is avoidable. Build these four habits and you'll almost never need the remediation steps:
.env file. Put your secrets in a file named .env and read them as environment variables โ never type a key directly into your app code..env to .gitignore. This is the one line that keeps your secrets off the tape entirely. Your .gitignore should contain:.env
.env.localYOUR_API_KEY_HERE.Before your next push, paste this into Cursor, Bolt, Replit, or whatever you're building with:
Audit this project for hardcoded secrets before I push to GitHub. Search all files for API keys, passwords, tokens, database connection strings, and private keys that are written directly in the code instead of loaded from environment variables. List every file and line you find, tell me whether a
.envfile is being used correctly, and confirm that.envis in.gitignore. Do not print the actual secret values back to me โ just the file names and line numbers.
That last sentence matters: you don't want your assistant echoing real keys into the chat log either.
If I delete the secret and force-push, is it gone?
No. The secret stays in earlier commits, and even a full history rewrite can leave copies in forks and caches. Rotating the key is the only thing that reliably makes it safe.
My repo is private โ am I safe?
Safer, but not safe. Private repos can be cloned, forked, or made public later, and anyone with access can read the full history. Treat any committed secret as compromised and rotate it.
Do I really have to rotate the key if I cleaned the history?
Yes โ and rotate first. Once a secret has been pushed anywhere public, assume a scanner has already grabbed it.
What's the difference between BFG and git-filter-repo?
Both rewrite git history to remove sensitive data. BFG is simpler and faster; git-filter-repo offers more control and is favored by git's core developers. Follow your chosen tool's official docs rather than improvised commands.
Does GitHub catch this automatically?
Partly. GitHub scans public repos for known key patterns and alerts the owner, and many providers auto-revoke flagged keys โ but it doesn't catch everything. Your .gitignore and a pre-commit scanner are your real defense.
Discover more content: