Your OpenAI key leaked.
Here is the calm fix.

Whether a bot found your sk- key or OpenAI emailed to say it was disabled, the steps are the same and the order matters. Kill the key at OpenAI, find where it leaked, check your usage for abuse, then clean up git history last. This page walks it in plain English.

Jump to the runbook → Check what else is exposed (free)

First, breathe. Then rotate.

A leaked OpenAI key is a bad afternoon, not a disaster, as long as you do one thing quickly: make the leaked key stop working. Everything else can wait a few minutes. That one thing cannot.

Here is why the clock matters. Automated scrapers watch public GitHub commits and copy anything shaped like an sk- key, often within minutes of the push. A copied key can be used to run up charges on your account until it is revoked. At the same time, OpenAI runs its own detection: it scans the public internet and published app bundles for its key format, and its security policy is to disable a key it finds exposed and email the owner. So there is a real chance your key is dead before you finish reading this.

Either way, the move is the same. Revoke the key at OpenAI, put a fresh one in place, then figure out how it got out so the new key does not follow it. The rest of this page is that, step by step.

Start the runbook →

The runbook, in order

Five steps. The first one is the only urgent one. Do it now, then work down the list calmly.

1. Revoke the leaked key and create a new one

Open platform.openai.com/api-keys. This is the single page that matters most.

  1. Click Create new secret key at the top. Give it a name, then copy the new key. OpenAI shows it only once, so copy it before you close the box.
  2. Put the new key everywhere the old one lived: your local .env, your CI secrets, and your deployed environment (Vercel, Netlify, Cloudflare, wherever you host). Restart your dev server and redeploy so nothing is still running on the old key.
  3. Now kill the leaked one: click the trash icon next to it and confirm Revoke key. A revoked OpenAI key stops working right away.

If the key is already public, you can flip the order and revoke first, then create the replacement. A minute of downtime beats a minute of a live key on the open internet. To confirm the old key is truly dead, make one test call with it. It should be rejected with an authentication error (a 401). If it still works, you rotated the wrong key.

2. Read the "your key was disabled" email, and find where it leaked

If OpenAI emailed you saying a key was leaked or disabled, that email is not a false alarm and not spam. It means exactly one thing: your key was found somewhere public and OpenAI acted on it. The key in that email is already dead. Your job now is to find the door it walked out of, because a new key put back into the same spot leaks the same way.

The two usual doors, in order of how often they are the culprit:

  1. A public git repo, often an old commit. The key does not have to be in your current code. It only has to have existed in history once. Search your full history for your key's prefix: git log -S "sk-" --all --oneline. If any .env file ever shows up in history, treat every key that was ever in it as leaked.
  2. Your frontend bundle. This is the classic one for apps built with AI tools. An OpenAI key belongs on your server, never in the browser. If you put your key in a variable prefixed NEXT_PUBLIC_ or VITE_, it ships to every visitor by design. Open your live site, view the page source and the built JavaScript, and search for your key's prefix. If it is there, anyone who loaded your site has it. The real fix is to move OpenAI calls behind a small backend route, not just to rotate.

There is a third, quieter door: a misconfigured server handing out .env or config files to anyone who requests them. Our free scan checks for exactly that, passively and with no signup. More on that below.

3. Check your usage and billing for abuse

Once the key is dead, find out whether anyone spent your money before you closed the door. Open the usage page and look at the days since the leak. You are looking for spikes you did not create and models you do not use. Then open your limits page and set a monthly budget with an alert if you have not, so a future mistake shows up as a warning early. (OpenAI's budget is a soft alert threshold, not a hard stop, so treat it as an early-warning, not a wall.)

The honest part about refunds: OpenAI does not promise to forgive fraudulent charges from a leaked key, and there is no guaranteed refund button. Sometimes support will credit clearly-unauthorized usage from a first-time leak, and sometimes they will not. It is worth asking, politely, through OpenAI help, with a short factual timeline: when the key leaked, when you revoked it, and which usage is not yours. Go in hoping, not expecting. The reliable protection is the early revoke and the budget alert you set in the step above, not a refund after the fact.

4. Rotate anything that leaked alongside it

Keys travel in packs. The habit that put your OpenAI key in a public commit almost certainly put its neighbors there too. If a .env file was exposed, assume every secret in it is compromised: your database URL, your Stripe key, your Supabase service role key, other AI provider keys. Rotate all of them, not just the one OpenAI flagged.

Our general leaked-key runbook has the exact console page and steps for each major provider. If Stripe, Supabase, Anthropic, or a raw .env file is in the mix, we have dedicated pages: Stripe, Supabase service role key, Anthropic, and an exposed .env file.

5. Scrub git history, last

Only now do you rewrite history. This step matters, but it is cleanup, not containment. Scrubbing the key out of your commits does not un-leak it. By the time you scrub, any bot that wanted the key already has it. Revoking the key in step 1 is what actually removed the risk. Scrubbing alone is theater.

When you do it, use git filter-repo or BFG, then force-push. Know the limits, which GitHub spells out in its own docs on removing sensitive data: the old commits can still live in forks, in other people's clones, and in cached views on GitHub itself. This step protects the next person who reads your repo. It does not protect the key. Step 1 did that.

What OpenAI and GitHub catch automatically, and what they miss

There are two safety nets running in the background. Both are real, and neither is enough on its own.

OpenAI's own scanning. OpenAI scans the public internet and published app store bundles for its key format. When it finds a key, its security policy is to disable it and email the account owner. That is the "your key was disabled" email people get. It is a genuine safety net, and it is why some keys are dead before their owner notices.

GitHub secret scanning. OpenAI is a GitHub secret-scanning partner. Secret scanning runs automatically and for free on public repositories, across your whole git history. When it finds an OpenAI key format, GitHub reports it directly to OpenAI so they can act, which can include disabling the key. Separately, push protection blocks pushes that contain known key formats before they land.

Where the nets have holes. A key in your frontend JavaScript bundle is not in a git repo, so repo scanning does not see it. A key in a notebook cell, a base64 blob, or a private gist can slip past pattern matching. New or unusual key formats can lag behind the scanners. And scrapers race the defenders, so a fast bot can copy a key before OpenAI reaches it. The takeaway is simple: treat these nets as a bonus, not a plan. Assume the key was copied, and rotate it yourself regardless.

Confirm your live site is actually clean

You rotated the key and scrubbed the repo. One question is still open: is anything else exposed right now on your live site? A leaked key rarely travels alone, and the frontend-bundle leak in particular does not show up in your git history at all.

So finish with a check. Our free scanner looks at your live site passively and needs no signup. It checks for the kinds of exposure that leak keys in the first place: a reachable .env file, config files served to the public, secrets sitting in your frontend bundle.

And because "trust us" is not evidence, we publish a reproducible benchmark. In a blind run on a 30-case stratified sample of OWASP Benchmark 1.2, the audit scored an F1 of 93.8%. That is a 30-case sample, not the full benchmark, and we say so right in the results.

Run the free scan →

If you build with AI, catch this before you push

Most leaked OpenAI keys come from the same handful of mistakes: a key pasted into frontend code, a .env that never made it into .gitignore, a config file committed once and forgotten. Those are easy to catch before they ship, and much cheaper to catch there than on your invoice.

We built a free, open-source plugin for Claude Code that runs a 48-check audit catalog over your project in plain English, and a guided key-rotation walkthrough (/lictor-rotate) for when a key does leak. Install it with:

/plugin marketplace add Raffa-jarrl/Lictor-AI
/plugin install lictor-security-suite@lictor-ai

Building on tools like Lovable or Bolt? Those generators have their own common leaks. See our security checklist for Lovable, our notes on a leaked key from Bolt, and our Claude Code security guide.

Next time, know in hours, not on the invoice

Today you found out about the leak from a bot, an OpenAI email, or a surprising bill. That is the worst possible alarm system.

Lictor's continuous monitoring watches your exposed surface for you, from $49/mo, so the next leak is a small notification while it is still small, not a shock on the invoice. It is run by the same person who wrote this runbook: a security engineer with 20 years in the field who does real responsible-disclosure work.

See continuous monitoring → Start monitoring

Questions people ask at this point

What happens if my OpenAI key leaks?

Two things race. Scrapers copy keys from public commits within minutes and can run up charges until the key is revoked. Meanwhile OpenAI scans the public internet and app bundles for its key format and disables keys it finds, then emails you, so your key may already be dead. Either way the fix is the same: revoke the key at platform.openai.com/api-keys, create a fresh one, find where it leaked, and check your usage page for charges you did not make.

Does OpenAI automatically disable leaked keys?

Often, yes. OpenAI scans the public internet and published app bundles for its key format and, per its security policy, disables a key it finds exposed and emails the owner. It is also a GitHub secret-scanning partner, so keys found in public repos get reported straight to OpenAI. But do not rely on it: coverage is not perfect, scrapers can win the race, and a key in a frontend bundle may slip past. If you got the disabled email the key is dead already. If you did not, revoke it yourself anyway.

How do I rotate an OpenAI API key?

Open platform.openai.com/api-keys. Click Create new secret key, name it, and copy the new key (shown only once). Put it in your .env and every deploy environment, then restart and redeploy. Then revoke the old one: click the trash icon next to it and confirm Revoke key. A revoked key stops working immediately, so a test call with the old key should return an authentication error (a 401). If the key is already public, revoke first and create the replacement second.