Playbooks / Leaked API key

Playbook

Leaked API key: what to do in the first hour

A key was committed to a public repo, pasted into a chat, shown in a screenshot or logged somewhere it shouldn't be. Treat it as compromised, even if you deleted it seconds later, and work through these steps now.

Last checked

Is someone using it right now? If you see charges, requests or changes you didn't make, revoke the key immediately and accept the downtime. A broken checkout for twenty minutes costs less than an attacker with your production key. Then come back to step 2.

Why deleting it isn't enough

Bots scan public GitHub for keys within minutes of a push. Removing the commit, force-pushing or making the repo private doesn't help: the value may already be copied, and it stays in forks, clones, caches and CI logs. The only fix is to make the leaked key stop working. Everything else is cleanup.

The steps

  1. Find where it leaked. Check your repo, logs and chat for the value, and remove it. Don't paste the value anywhere new while you look, including into a search box or an AI chat.
  2. Create a new key. In the account that owns the leaked key, create a replacement with the same permissions, or narrower ones if you can. If an AI agent created or saw the old key, treat that copy as exposed too.
  3. Save it and deploy it everywhere. Store the new value safely, update every environment variable and CI secret that held the old one, and redeploy so running apps pick it up.
  4. Verify it works. Run a request or a deploy and check that nothing is failing. Keep this short: you're measuring minutes, not days.
  5. Revoke the leaked key now. Do this as soon as the new key works. Until the old one is revoked, anyone who has it can still use it. If several projects share the key, revoking it once covers them all.
  6. Check for misuse. Look through the provider's usage, audit and billing logs since the leak for anything you don't recognize: requests, new users, new keys, changed settings, unexpected spend.
  7. Find other copies. Search for the same value in old .env files, CI secrets, deploy logs, error trackers, chat history and AI agent sessions. Remove what you find.
  8. Close the gap. Turn on secret scanning and push protection for your repos, and move to restricted or scoped keys so the next leak can do less.

If the key was pushed to GitHub

A pushed key is a common leak. Revoke it first, then deal with the history.

Why deleting the commit isn't enough

So the key is compromised, whatever you do to the repo. GitHub's own guidance is that the first step is to revoke or rotate the secret, and that once you have, rewriting history may not be warranted. For an OpenAI key, see OpenAI. For Stripe, see Stripe. For AWS access keys, see AWS. If the provider isn't listed, find it here or use its own docs.

Secret scanning and push protection

GitHub's secret scanning runs automatically and for free on public repositories, and scans your entire Git history on all branches. For secrets from its partner providers, GitHub notifies the provider, which can then take action such as revoking the credential. GitHub tells the provider, which may revoke it, but revocation isn't guaranteed. Those detections are reported to the provider and aren't shown in your repository alerts, so you may never see one. Check the provider's console and email, and revoke the key yourself either way.

Push protection blocks a push that contains a supported secret before it reaches the repository. It protects you only for the patterns it supports, and anyone with write access can bypass it by giving a reason. Turn it on for your repositories, and treat it as a seatbelt, not as a fix for a key already pushed.

Remove it from history afterwards

Once the key is revoked, removing it from history is hygiene: it stops people copying a dead key into new places and keeps scanners quiet. GitHub's docs describe using git filter-repo with the --sensitive-data-removal option, and note that you must coordinate with everyone who cloned the repo. Pull request refs can only be cleaned up by GitHub Support. Do this after the new key works, never instead of revoking.

The order, in short

If the key isn't being abused yet: new key → deploy everywhere → verify → revoke, all within the hour if you can. If it is being abused: revoke first, then do the rest while the app is down. Either way, the leaked key should be dead within hours, never days.

Checking for misuse

If you find fraudulent charges, contact the provider's support with the dates and what you've already revoked. Many providers have a process for this, and acting quickly helps. Provider-specific details are on each provider page, for example Stripe, AWS, OpenAI and GitHub.

Database passwords

A leaked connection string is the same emergency. Create a second database user with the same permissions, move every connection to it, verify, then drop the old user. If you reset the password in place instead, the old one stops working at once, so be ready to update every connection string immediately.

Write it down

Record when the key leaked, where, when you revoked it and what you found in the logs. If customer data might have been accessed, you may have obligations to tell users or regulators, and the timeline is what you'll need.

Prevent the next one

Do this in StackHangar

StackHangar runs this playbook against your own stack. Your vault already knows which account owns the key and every project and deploy target that holds it, so step 3 isn't a guessing game.