All posts

You pushed an API key: the first ten minutes, in the right order

Security · 4 min read ·

You ran git push, looked at the diff on GitHub, and saw your API key sitting in plain text. The instinct is to delete the commit and force-push before anyone notices. Do not start there. Treat the key as compromised from the moment it was pushed, and spend the first minute at the provider, not in git.

Why deleting the commit does not un-leak it

A push copies your history to places you do not control. Anyone who cloned or forked the repository has the commit. Automated scrapers watch public pushes for anything shaped like a key, and they are fast. Caches and mirrors can keep a copy after you rewrite your own branch. Removing the commit cleans one copy, yours, and leaves the key valid everywhere else. The only action that makes every copy useless at once is revoking the key.

Commit with the key, pushed Forks and clones Key scrapers Caches, mirrors Your branch delete the commit: only this copy goes
Rewriting history reaches one of these four copies. Revoking the key makes all four worthless.

The order that limits the damage

This is general guidance rather than a rule from any one provider, but the order matters more than the speed of any single step.

1. Revoke or rotate the key at the provider. Create a new one, swap it into your deployed environment, delete the old one. Until this is done, everything else is cosmetic.

2. Check the provider's usage and billing dashboard for calls you do not recognise, from the moment of the push onward. If there are any, you now have an incident to report, not just a mistake to tidy.

3. Take the secret out of the code. In Laravel the key belongs in .env, read through a config file, and the code reads it with config():

// config/services.php
'anthropic' => ['key' => env('ANTHROPIC_API_KEY')],

// anywhere in the app
$key = config('services.anthropic.key');

Never call env() outside a config file. After php artisan config:cache, which most deploys run, env() returns null outside config, so a key read directly in a controller tends to get hard-coded "just to make it work". Check that .env is in .gitignore, and keep a .env.example with fake placeholder values so nobody needs the real file to start the app.

4. Only then, if you want, clean the history with git filter-repo or BFG. It is hygiene, not a fix: it needs a force-push and everyone re-cloning, and it does nothing about the copies in the first diagram.

5. Stop the next one. Turn on secret scanning and push protection, add a pre-commit scanner, and give each environment its own scoped key with a spending limit, so the next leak is small. Then write down what happened while you still remember it.

1. Revoke the key 2. Check usage 3. Move to .env, config() 4. Clean history 5. Add push protection minute one optional, never first steps 2 to 5 only matter once step 1 is done
Revoke before you clean. History rewriting is the fourth step, not the first.
A leaked key is fixed at the provider, not in git. Revoke it first; everything after that is cleanup.

What GitHub now does for you

GitHub announced on 2026-10-13 that secret scanning detects new secret types from Salesforce, Anthropic and Cloudsmith, and that the two new Anthropic types, anthropic_service_api_key and anthropic_user_api_key, are blocked by push protection by default. According to GitHub, repositories with secret scanning enabled, free public ones included, have commits containing those keys blocked automatically. GitHub also says partner secrets found in public repositories are forwarded to the issuer so they can be revoked before abuse, and that user secrets raise alerts in public and private repositories. That is a safety net worth turning on, but it covers the types GitHub knows about, so the order above is still yours to follow when something slips through. If you have not enabled secret scanning on your repositories, do it today, then add a pre-commit scanner so the key never leaves your machine in the first place.

Source: GitHub Changelog, 2026-10-13.

Notes from readers

  1. No notes yet. The first one is the bravest.
Building something like this? I can help. Message me on WhatsApp