Ask an AI assistant to add AI chat, email or payments to your app and it will usually get it working. Look closely, though, and the key that makes it work may be sitting in your app's browser code, where anyone can copy it. It's one of the most common problems in AI-built apps, and one of the easiest to check.
This guide explains how keys end up in the front end, which ones are fine to be public, how to find the rest, and how to fix a leak properly.
How keys end up in the browser
Many AI-built apps are React projects built with Vite. Vite puts any environment variable whose name starts with VITE_ into the code it sends to the browser, and its documentation says plainly that these variables shouldn't contain sensitive information such as API keys. An assistant that names a key VITE_OPENAI_KEY to make a feature work has published it.
Keys also leak by being pasted straight into source files, committed to the repository, or shared in a chat with an AI tool and copied from there into code.
Which keys are meant to be public
Some keys are designed to be in the browser, because they only identify your account and the real protection lives elsewhere:
- Supabase publishable or
anonkey: safe only when Row Level Security protects every table - Stripe publishable key (starting
pk_) - Analytics and map keys that are restricted to your domain
Everything else stays on the server: secret and service_role database keys, Stripe secret keys (starting sk_), AI provider keys, email service keys and anything that can spend money or read private data.
How to find exposed keys
- Search your environment files. List every variable with a
VITE_(orNEXT_PUBLIC_) prefix and ask whether it's meant to be public. - Search the code. Look for
sk_,secret,service_role,api_keyand long random strings. - Check the live site. Open your app, open the browser's developer tools and search the loaded scripts for the same words. This is exactly what an attacker does.
- Check the history. Deleting a key from the latest code doesn't remove it from earlier commits. If your repository is on GitHub, its secret scanning can flag known key formats.
How to fix a leak
Once a key has been public, assume someone has it. Create a new key at the provider and revoke the old one. Moving it out of the front end only protects the new key.
- Move the call to the server. The browser asks your own server function, and the server calls the provider with the key.
- Store the key in your host's environment settings, never in the code or the repository.
- Add limits. Use the narrowest permissions the provider offers, restrict keys to your domain where possible, and set spending limits on AI and email accounts.
- Protect the new server function. Check that the user is signed in and allowed to use it, or you've simply moved the open door.
Why this matters when you leave a builder
Platform exports rarely include secrets, so every key has to be set up again on the new host. That's the right moment to move keys out of the front end, rotate anything that was exposed, and put each account in your business's name.
On every migration, AppExit checks for exposed keys, along with data that anyone can read, sign-in and access rules, and outdated packages, before and after the move, and tells you what we find. Please never send us keys or passwords through our forms; we arrange least-privilege access with you separately. Read the five security problems we check for, or start your order.
Sources
Sources checked November 2026. AppExit is not affiliated with any company named. Brand names belong to their owners.