Exposed API keys
In one paragraph
An exposed API key is a live credential — for Supabase, OpenAI, Stripe or similar — that ends up in your app's browser bundle or public repo, where anyone can copy it. It's the single most common finding in AI-built apps, because the key makes the app work whether or not it's safely placed. The fix is to move every secret server-side, rotate anything that was ever exposed, and verify the live bundle is clean.
A secret key is meant to live only on a server. The moment it's compiled into the JavaScript your browser downloads — or committed to a public repo — it's readable by anyone who opens DevTools, and attackers scan for exactly this. An exposed OpenAI key runs up your bill; an exposed Stripe secret or Supabase service-role key is a full account compromise.
Why it happens
The key is the path of least resistance
To make a feature work, the model grabs the key that always works and puts it where the code that needs it runs — which, in a frontend app, is the browser. It compiles cleanly and the demo works, so nothing flags it.
Framework prefixes that publish by design
NEXT_PUBLIC_ and VITE_ variables are compiled into the client bundle on purpose. A secret given one of those prefixes to "fix an undefined variable" is now public.
Pasted into the repo to unblock a build
A key hardcoded directly into a file, or dropped into a committed .env, rides along into git history — where it stays even after you delete it.
Check it yourself
- Open your live site, then DevTools → Sources, and search the bundle for sk-, SECRET, PRIVATE, and service_role.
- Search your repo and its full git history for the same patterns — a deleted key is still in old commits.
- Check that no secret uses a NEXT_PUBLIC_ or VITE_ prefix.
How to fix it
- Move every secret call to the server — an API route, a serverless function, or a Supabase Edge Function.
- Rotate any key that was ever in client code or committed — assume it's compromised.
- Keep only publishable/anon keys in the frontend, and make sure those are safe by design (for Supabase, that means RLS is on).
Not sure if your app has this?
SafeLaunch checks your repo and live site in about 30 seconds — this issue and every other — and gives you a prompt to paste back into your builder to fix each finding.
Most common in apps built with
Exposed API keys FAQ
How do I know if my API key is exposed?+–
Open your deployed site, view the page source or the DevTools Sources tab, and search for your key or for patterns like sk- and service_role. If it's there, it's public — rotate it and move it server-side.
Is it safe to put an API key in the frontend?+–
Only a key designed to be public, like a Supabase anon key or a Stripe publishable key. A secret key (sk-, service_role, or anything marked private) must never reach the browser.
Someone found my key — what do I do?+–
Rotate it immediately so the old one stops working, move the call server-side so the new one never reaches the browser, and check your provider's usage logs for anything you didn't do.