The $55k mistake: LLM keys in the wrong place

July 23, 2026

We’ve spent ten days on cost and abuse. Now the base the whole series rests on — the security plumbing — and it starts with the least glamorous, most common way to lose five figures overnight: the key in the wrong place. The $55k Gemini bill, and the others like it, almost never begin with a clever exploit. They begin with a credential a stranger could read.

An LLM key is a bearer credential for your wallet

That’s the whole mental model. Whoever holds your API key can spend your money, at your provider, until you notice and revoke it. There’s no second factor, no per-charge approval — possession is authorization. Treat it exactly like you’d treat a signed blank cheque, because that’s what it is.

Ship a key to the browser and you've shipped it to everyone.

So the rule is simple and absolute: never ship the key anywhere the user can read it.

Where keys leak

The handling discipline

None of this is new. It’s the credential hygiene the rest of security has practiced for decades, pointed at a new, expensive target:

The pattern in code

The whole discipline fits in a few lines. The anti-pattern is a literal key in code that ships; the fix is loading the real key from the environment at the gateway, and handing your apps a virtual key instead:

# ANTI-PATTERN — the provider key is baked into code that ships to users:
client = OpenAI(api_key="sk-proj-abc123...")     # now in the bundle, the repo, git history

# GOOD — the real key lives ONLY at the gateway, read from the environment at
# startup (your secrets manager injects it; it's never hardcoded or committed).
import os
provider_key = os.environ["OPENAI_API_KEY"]      # server-side only; rotate = swap + restart
gateway = OpenAI(api_key=provider_key)           # only the gateway calls the provider

# Your apps never see that key. They hold a scoped, rotatable VIRTUAL key the
# gateway issues, and point base_url at the gateway — revoke it without touching the real one.
app = OpenAI(
    api_key=os.environ["GATEWAY_VIRTUAL_KEY"],   # per-app, revocable on its own
    base_url="https://your-gateway/openai",
)

The first line is the entire disaster in miniature: a bearer credential compiled into something a stranger can read. The fix isn’t clever — the real key is read from os.environ at server startup, so rotation is a config swap and a restart, never a code change or a redeploy of your app. Everything downstream, your own services included, authenticates with the gateway’s virtual key, which you scope per app and revoke on its own.

Where the gateway helps

Routing every call through the gateway means the real provider key lives in exactly one server-side place. Your app code holds a per-user virtual key the gateway issues (the same virtual keys that carry the caps and quotas from Day 4) — so even your own services never handle the master credential, and you can revoke a virtual key without rotating the real one.

This is the instinct 20 years of logins, key management, and WebAuthn work builds: a credential is a liability you minimize the exposure of. An LLM key is just a new, unusually expensive bearer token, and it deserves the same paranoia.

One honest boundary: perfect key hygiene stops the leaked-key catastrophe — the headline five-figure bill. It does not stop abuse by a legitimate, authenticated user; that’s what caps and quotas are for. Different failure, different control.

Next in the series — Day 12: rate limiting you already know, now for tokens — because once the key is safe, the next question is how fast any one holder can spend.


If your AI feature ships a key to the browser, bakes one into an app, or has one sitting in git history, that’s a five-figure bill waiting for a scraper — and finding it is part of the audit I do. Every message comes straight to me — I read and reply to each one myself, usually within a day, and what readers send shapes what I build next. It’s just me for now, so that’s genuinely true; it won’t be forever. Send me your setup and I’ll tell you where your keys are exposed — free, within a business day.

Free live workshop: cap your AI spend (Oct 8)

A hands-on 90-minute session — wire a fail-closed spend cap + cost-aware rate limiting against a real stack, live, so a leaked key or runaway agent can't run up your bill. Full details & times → Save your seat (and get each new lesson as it lands):

Double opt-in — one email to confirm. The lessons are free; the course is optional. No spam, unsubscribe anytime.