Your site hands its code to everyone
Every visitor's browser downloads your app's JavaScript in full. That is how the web works, and it means anything placed in that code is public information with extra steps. AI builders blur one line constantly here: the line between keys that are meant to be public and keys that are meant to live only on a server. Put a secret one in the browser bundle during development, watch the app work, and nothing ever tells you to move it. It ships.
Which keys are which
Publishable and public keys are designed to be seen. Stripe's publishable key, Supabase's anon key, and a Firebase web config identify your project and are safe in the open, provided the access rules behind them are right. Secret keys are a different species. A Stripe secret key can move money and read customers. An OpenAI key spends your money on every call. A Supabase service role key bypasses every row level policy and reads the whole database. Those three belong in server side environment variables and nowhere else, not in client code, not in a mobile app, and not committed to your repo, where history keeps them even after you delete the line.
Check your own site in five minutes
Open your live site, view the page source and the loaded JavaScript files, and search them for the shapes of trouble: the characters sk_live or sk_test for Stripe, sk- followed by a long token for OpenAI style keys, and long tokens that decode as service role keys for Supabase. Then search your repo, including its history, for the same shapes, because a key committed once in month one is still sitting in the history in month six. Builders add a second trap here: the key is sometimes in an environment file that got bundled anyway, or in a settings page the app renders for admins and ships to everyone.
If you find one: rotate first, clean up second
Order matters and the natural instinct gets it backwards. Do not start by cleaning the code while the leaked key still works. Go to the provider, generate a new key, and revoke the old one, so the copy sitting in browsers and git history becomes worthless. Then move the new key into a server side environment variable, update the code that used it, and rebuild, so the fresh bundle contains nothing sensitive. Check where else the old key travelled: old preview deployments, a screenshot in a support thread, a public repo fork. Finally, look at the provider's usage logs for the period the key was exposed, because the honest question after a leak is not just whether it is closed, but whether anybody used it while it was open.
A note on why this post does not hand you a prompt for the cleanup: the rotation itself is dashboard work, and the risky step is the order of operations and the verification, not the typing. A prompt that helpfully removes a key from your code without rotating it first leaves the live leak fully working.
Verify it: the old key is refused by the provider, the new key exists only in server side environment settings, and a fresh search of the built site and the repo history finds no secret key shapes.
FAQ
My Stripe publishable key is visible in my checkout page. Is that a leak?
No. Publishable keys are meant to be public and can only start the checkout flows you have configured. The secret key is the one that must never appear, and it starts with different characters, sk_live rather than pk_live.
I deleted the key from my code and redeployed. Am I done?
Only if you also rotated it. The deleted version lives on in your repo history and in any copy of the old bundle a browser or an archive kept. Rotation is the step that actually closes the leak.
The key was only in a test file or a preview deploy. Still serious?
If it is a live secret key, yes. Previews and test files get indexed, shared, and screenshotted. Treat any live key that reached a browser or a repo as leaked, rotate it, and then argue about how serious it was.
Ground Crew note
Keys and secrets are check 02 on the free production audit, where we scan the bundle and the repo history and tell publishable from secret properly, because the difference decides whether you have a cleanup or a breach. The rest of the list is on the post launch checklist, or request the free audit.