ShipWatchFree scan

Leaked an API key? The rotate-first playbook (OpenAI, Stripe, Supabase, AWS, Google)

You found a key where it shouldn't be: in your JavaScript, a public repo, a screenshot. Every minute it stays valid is a minute someone else can use it. This is the order to work in, with where each provider's revoke button lives.

Short answer: Revoke or roll the key with the provider first, before touching code. Then put the new key in a server-only environment variable, redeploy, review usage for anything you didn't do, and only then clean the old key out of git history. Deleting the line from your code does not make the old key safe.

This page is for after a hit. To find out whether you have a leak in the first place, use the leaked API key checker. If you're cleaning up a key an AI editor typed into your code, the Cursor hardcoded keys guide covers the repo side.

The order, and why it matters

  1. Revoke or roll the key with the provider. This is the only step that stops abuse.
  2. Replace: create a new key and store it as a server-only secret.
  3. Redeploy so your app uses the new key from the server side.
  4. Check usage for activity you didn't cause.
  5. Purge history: remove the old value from git and anywhere else it was pasted.

Beginners usually do this backwards: they delete the line, push, and assume they're done. The old key keeps working until the provider kills it.

Step 1: Revoke or roll, per provider [manual]

If the provider offers a grace period for the old key, set it as short as your redeploy allows.

Step 2 and 3: Replace and redeploy

The new key goes somewhere the browser can't reach: a Supabase Edge Function secret, a Vercel or Netlify environment variable used only in server functions, or a Cloudflare Worker secret. If the leak happened because of a VITE_ or NEXT_PUBLIC_ prefix, read the VITE_ or NEXT_PUBLIC_ guide before redeploying, or the new key will leak exactly like the old one.

I just rotated a leaked API key. Find every place this app reads the old key, including VITE_ or NEXT_PUBLIC_ variables and hardcoded strings. Move all calls that use it into a server-side function that reads the new key from a server-only environment variable, make the frontend call that function, and confirm no client-side file references the key.

Step 4: Check usage [manual]

Look at the provider's usage or billing page for the window the key was exposed: OpenAI usage, Stripe's recent payments, refunds and payouts, AWS CloudTrail and billing, Google Cloud's API metrics. If you see charges you didn't make, contact the provider's support with the dates.

Step 5: Purge it from git history [manual]

If the key was ever committed, it's still in old commits. Find it with:

git log -p --all -S "sk-proj-" | head -40

GitHub's guide to removing sensitive data recommends git filter-repo, followed by a force push, and warns that existing clones and forks still contain the data. That's why this step comes last: it's tidy-up, not protection. If your .git folder was ever served on your website, read .git folder exposed too.

Make it stick

What the free scan checks here (and what it doesn't)

The scan reads your live HTML and up to 25 linked scripts and flags Stripe sk_live_/rk_live_, OpenAI sk-proj-, Anthropic sk-ant-, AWS AKIA/ASIA, Google AIza, and Supabase service_role and sb_secret_ keys. It also checks whether /.env or /.git/HEAD is publicly served, HTTPS and its redirect, and four security headers.

It can't tell whether a key is revoked, read your git history, or see provider usage. Those steps are yours [manual].

FAQ

Should I fix the code before revoking the key?
No. Revoke first. The old key is already copied wherever it leaked, and fixing the code doesn't recall those copies. A few minutes of downtime while you swap keys is cheaper than an attacker's bill.
Is rewriting git history enough instead of rotating?
No. Anyone who cloned, forked or cached the repo before the rewrite still has the key. History cleanup is a final tidy-up step, done after the key is dead.
How do I know the old key is gone from my live app?
Search your deployed JavaScript for its first characters, or run the free scan. It reads your live page and up to 25 linked scripts and flags Stripe, OpenAI, Anthropic, AWS, Google and Supabase secret keys.

Scan your app free in 30 seconds

Paste your live URL for a plain-English report with fix prompts. If you keep shipping, weekly monitoring re-checks it: Solo $19/mo or Pro $49/mo.

Scan my app free