Your API key leaked — a step-by-step response
A leaked key means a growing bill. The first steps take a minute, and their order matters more than speed.
2 min · · Updated · security · API keys · development
Keys in public repositories are found by automated scanners, usually faster than you notice yourself. The order of your response matters more than its speed: start with the wrong step and the damage keeps growing while you tidy up.
First: revoke the key
Do not rotate it, do not move it elsewhere, do not start rewriting git history. Revoke first — that disables the key immediately and permanently, and from that moment the damage stops growing.
Everything else can be done calmly.
A common mistake is to issue a new key, switch services over to it, and revoke the old one "once everything works". During that window the old key keeps working for whoever found it.
Second: check what was spent
Open your usage history and compare it against a normal day. Look for three things: a spike in request volume, unfamiliar models, and activity during hours when you do not work.
No spike means you were faster than the scanners. A spike means you should record the amount — you will need it if you contact support.
Third: issue a new key and store it properly
The new key must not land where the old one leaked from. The practical minimum:
Keys live in environment variables or a secret manager, not in code and not in a config file that sits in the repository.
.gitignore covers .env, .env.local and anything else holding secrets. Confirm the entry exists before the first commit, not after.
One key per service. A leak then does not force you to rotate everything. Just note that the usage history (/v1/usage) is shared across the account and has no per-key filter; to see spend per key, log the X-Zukko-Cost-Micros header on your side (it is present on non-streaming responses) or set daily and monthly limits on your keys in the dashboard.
About rewriting git history
Deleting the file in a new commit is not enough: the old contents remain in history and are available to anyone who clones the repository. You can rewrite history, but that breaks every existing local copy.
The key point: cleaning history does not undo the leak. The key has been seen and may already have been copied. Revocation is mandatory; history cleanup is hygiene afterwards.
Avoiding it next time
Keys in screenshots are the second most common route after git. Before posting a terminal capture to a chat or a forum, check whether environment variables are visible in it.
Keys in logs come third. If you log request headers for debugging, make sure Authorization is not among them.
And build the habit of reviewing your active keys periodically: revoke any you cannot confidently tie to a specific service.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- Your Own Neural Network Proxy on Node.js: Keep the API Key Off the FrontendA small Express server between your frontend and the model API: the key stays on the server, and models, request size and rate are capped.
- DeepSeek API in Python: Requests, Streaming, JSON and Error HandlingReady code for DeepSeek V4.1 Flash and V4 Pro on the OpenAI SDK: a request, streaming, JSON parsing and careful error handling.
- Gemini API in Python: requests via the OpenAI SDK and OpenAI formatA working Gemini API example in Python with no extra library: change base_url in the OpenAI SDK, add streaming and JSON, and compare with google-genai.
- Anthropic SDK for Python: base_url, key and a first request via a gatewayThe official anthropic package for Python just needs a different address. We cover base_url, the key, streaming, token counting, caching and errors.