My API key leaked. What now?
You pushed a key to a public repo, or got a secret-scanning email, or found one sitting in your frontend bundle. This is a normal thing that happens to careful people. Here's what to do, in order.
Do this first
- Rotate the key. Not delete โ rotate. Generate a new one at the provider and revoke the old one.
- Then update wherever the app reads it from.
- Then check your usage and billing for anything you didn't do.
Everything else โ cleaning git history, working out how it happened, feeling bad about it โ comes after those three. A revoked key is a harmless string.
Why rotating is the only fix
The instinct is to delete the line, commit, and hope. That doesn't work, for three reasons:
- It's still in your git history. Anyone who clones the repo gets every previous version of that file.
- It may already have been copied. Public repositories are continuously scraped for credentials by automated tools. The window between pushing a key and it being harvested is frequently measured in minutes.
- Forks, caches and mirrors persist. Even a deleted repo can survive in a fork or someone's cache.
So the honest assumption is: if it was exposed, treat it as known. Rotating makes that irrelevant. Nothing else does.
Where to rotate, by provider
| Provider | Where | Also do this |
|---|---|---|
| OpenAI | platform.openai.com โ API keys โ revoke, create new | Check Usage for spend you don't recognise ยท full guide |
| Anthropic | console.anthropic.com โ API keys | Check Usage ยท full guide |
| Stripe | Developers โ API keys โ roll the secret key | Check Payments and Refunds for anything unfamiliar. Contact Stripe support if you find any. ยท full guide |
| AWS | IAM โ Users โ Security credentials โ deactivate, then delete | See the AWS note below โ this is the expensive one |
| Supabase | Settings โ API โ rotate service_role | Assume every row was readable ยท full guide |
| GitHub | Settings โ Developer settings โ Personal access tokens | Check recent activity on your repos |
| Google Cloud | APIs & Services โ Credentials | Add referrer/API restrictions to the replacement |
| Telegram | Message @BotFather โ /revoke | โ |
Rotating usually breaks your deployed app for a minute, because it's still using the old value. That's fine, and it's the correct order โ a briefly broken app is better than a live key in the wild.
Three cases that need more than a rotation
AWS keys
This is the one that generates the horror-story bills. Attackers use stolen AWS credentials to run compute โ usually crypto mining โ and they do it in regions you've never opened, because that's where you won't look.
After deactivating the key: check the Billing dashboard, then check EC2 in every region, not just yours. Also look at IAM for users or access keys you didn't create โ a common move is to create a second set of credentials so revoking the first one changes nothing. If you find charges, contact AWS support; they routinely waive fraudulent usage when you report it promptly.
Supabase service_role keys
That key bypasses Row Level Security completely, so while it was exposed, every row in your database was readable and writable by anyone holding it. Rotate it, then assume the data was read. If it included other people's personal information, you may have a legal obligation to tell them โ that's a data breach, not just a leak.
Live Stripe secret keys
Roll it immediately, then review Payments, Refunds and Customers for activity you didn't initiate. Stripe's support team deals with this often and are worth contacting early rather than late.
Then: clean up and prevent the repeat
- Get it out of the codebase.
Move the value to an environment variable, and make sure the file that held
it is gone from the working tree. Set the real value in your host's
dashboard โ Vercel, Netlify, Supabase and the rest all have an environment
variables screen. A
.envfile on your laptop is not read by your host. - Make sure
.envis ignored. Add.envand.env.*to.gitignore. If.envwas already committed, git keeps tracking it until you rungit rm --cached .env. - Consider rewriting history โ but don't rely on it.
Tools like
git filter-repoor BFG can strip a secret from past commits. Worth doing for tidiness and for anyone cloning fresh. It does not undo the exposure: forks and caches keep their copies. The rotation is what saved you; this is housekeeping. - Turn on push protection. GitHub can block pushes containing recognised secret formats, and it's free on public repositories. It catches this class of mistake before it becomes a public one.
- Check whether anything else is exposed. Keys rarely leak alone. The habit that put one in the code โ pasting a value in to get something working โ usually put several. Worth a look before you close the laptop.
On feeling stupid: don't. Every provider has a one-click rotation flow, GitHub built a scanner, and Stripe auto-detects leaked keys, because this happens constantly to experienced engineers. You caught it. That's the part that matters.
Check whether anything else leaked
vibecheck scans your project or your live URL for exposed keys and the mistakes that cause them, in plain English โ with a fix prompt you can paste straight into your AI tool. Free, and your code doesn't leave the scan.
Scan my app