// SECURITY
What does it mean when your API keys are exposed in the browser?
Updated 2026-08-11 · 5 min read
An exposed API key is a secret credential that ended up in code your visitors can read. Anything shipped to the browser (page source, JavaScript bundle, or network requests) is public, so a leaked Stripe, OpenAI, or database key can be copied and used to run up your bill or reach your data. Secret keys must live only on the server.
What it is
There are two kinds of keys: publishable keys, which are safe to expose (like a Stripe publishable key or a Supabase anon key), and secret keys, which are not. A secret key is like the master password for a service. If it appears anywhere the browser can see it, anyone who opens your app can take it.
Why it matters to you
A leaked secret key lets a stranger spend your money and reach your data with your own permissions.
- An OpenAI or cloud key can be used until your bill hits the limit.
- A Stripe secret key can read your customers and payments.
- A database service key can read or delete every row you have.
How to tell if your app has it
You can check this yourself in about two minutes, no tools required.
- Open your live app, then open developer tools (F12) and go to the Network tab.
- Reload the page and click through a few actions.
- Search the requests and the page source for "key", "secret", "sk_", "service_role", or "api". A secret key visible here is exposed.
How it happens in AI-built apps
AI builders optimize for "it works," so they wire keys wherever the code runs, which is usually the browser. In Vite/Next.js apps, prefixing a variable with VITE_ or NEXT_PUBLIC_ ships it to the client. Tools like Bolt and v0 frequently do this with keys that should have stayed on the server.
The fix
Move every secret key to the server and rotate anything that was exposed.
- Delete the exposed key in the provider dashboard and issue a new one (assume the old one is compromised).
- Store secret keys in server-side environment variables, never in VITE_/NEXT_PUBLIC_ vars.
- Call paid or privileged services from a server route or edge function, not from the browser.
Find every API key in this project that is exposed to the browser (including VITE_ and NEXT_PUBLIC_ env vars). Move all secret keys to server-side environment variables and call those services from a server route instead of the client. List which keys need rotating.Key takeaways
- Anything the browser can load is public, including keys in your JS bundle or network calls.
- Publishable/anon keys are fine to expose; secret/service keys are not.
- If a secret key was ever exposed, rotate it, moving it is not enough.
Sources
Frequently asked
Is the Supabase anon key safe to expose?
Yes. The anon key is designed to be public, but it is only safe if your Row-Level Security policies are correct, because that key is what the browser uses to query your database.
How do I know which keys are secret?
As a rule: keys that start with sk_, service_role, or are labelled "secret"/"private" in the provider dashboard must stay server-side. Keys labelled "publishable", "public", or "anon" are safe in the browser.