Guides · Updated October 15, 2026
I found an API key in my Lovable or Bolt app’s public JavaScript. What now?
Every visitor to your app downloads the same JavaScript files, and anyone can read them in the browser’s developer tools. Some keys are made to be public. The others can be handled in a clear order, which this guide walks through for apps built with Lovable, Bolt, Replit or v0.
First, check which key you found
Two common keys are designed for the browser:
- Supabase publishable key (starts with
sb_publishable_) and the older anon key. Supabase lists the publishable key as safe to expose, because Row Level Security (RLS) limits what it can reach (Supabase API keys). That only holds with RLS on for every table and policies scoped toauth.uid(). See is my Supabase anon key safe? - Stripe publishable key (starts with
pk_live_orpk_test_). Stripe lists it as safe to expose and says you can include it in front-end code, since it can’t create charges or read account data (Stripe API keys).
These must stay on a server:
- OpenAI API keys. OpenAI says never to deploy your key in client-side environments like browsers or mobile apps, and to route requests through your own backend (OpenAI key safety). Treat other AI providers’ keys the same way.
- Stripe secret keys (
sk_live_) and restricted keys (rk_live_). Stripe marks both as not safe to expose. - Supabase secret key (
sb_secret_) and the older service_role key. Both bypass RLS, so they must never leave your control.
Step 1: Rotate the key in the provider’s dashboard
Rotating means creating a new key and switching off the old one. Do this first: the provider keeps accepting the old key until you rotate it, even after you delete it from your code. Put the new key straight into a server-side secret (Step 2), never back into the frontend.
OpenAI. OpenAI says to rotate your key immediately from the API Keys page in the OpenAI platform if you believe it has leaked, then update the key in your app.
Stripe. On the API keys page in the Stripe Dashboard, open the overflow menu (⋯) next to the key and select Rotate key. Stripe asks when the old key should expire. If you pick a later time, both keys keep working until then, so for a leaked key choose Now, which deletes the old key right away.
Supabase. Supabase’s procedure for a leaked key (Supabase: leaked key): fix the cause of the leak first, create a new secret key under Settings → API Keys, replace the old key everywhere your app uses it, confirm every part of your app uses the new one, then delete the old secret key. For a leaked service_role key, replace it with a new secret key and then deactivate the legacy keys in the same section.
Step 2: Move the call to the server
The new key needs a home the browser can’t see.
A Supabase Edge Function with secrets. An Edge Function runs on Supabase’s servers. Add the key under Edge Function Secrets in the dashboard, or with supabase secrets set, and read it in the function with Deno.env.get (Edge Function secrets). Your frontend calls the function, and the function calls OpenAI or Stripe.
Lovable Secrets. Lovable stores secrets encrypted, injects them into your Edge Functions, and never sends them to the browser (Lovable Secrets). Add one under More → Cloud → Secrets, or through the secure input Lovable shows in chat. Variables starting with VITE_ are built into the browser bundle, so never give a private key that prefix. Lovable needs the .env file committed to your repository, so keep only public values in it. Projects connected to their own Supabase project manage secrets in Supabase instead.
Bolt Secrets. Click the database icon at the top center of the screen, then Secrets, enter a name and value, and click Create secret (Bolt secrets). Bolt says these are used by your server functions so private information never ends up in your users’ browsers.
Then ask your builder to call that function instead of the provider, and confirm the key no longer appears in your live app’s JavaScript.
Step 3: Remove the old key from code and git history
Delete the key from your source files. It can still sit in earlier commits, which GitHub’s guide covers (GitHub: removing sensitive data). GitHub recommends git-filter-repo and warns that rewritten history can still be reached in clones, forks, cached views on GitHub, and pull requests that reference the old commits.
That’s why rotation matters more than deletion. GitHub says that once a secret is revoked or rotated it can no longer be used for access, and rewriting history may not be needed after that. It also suggests tools like gitleaks in a pre-commit hook to catch a key before it’s committed again.
Step 4: Check usage and set limits
Next, look at what happened while the key was public.
- OpenAI. Review the Usage page. OpenAI lets you set monthly spend limits for your organization and each project; turning on Enforce a hard limit makes requests fail with a 429 error once the limit is reached, and enforcement isn’t instant (OpenAI spend limits).
- Stripe. On the API keys page, the overflow menu next to each key has View request logs, which opens Workbench with the requests made using that key.
- Supabase. The Logs page in your project dashboard lets you search recent API Gateway and Postgres activity, among other log types (Supabase logs).
Step 5: Add rate limits on AI calls
A spend limit caps the total bill; a rate limit controls how often one person can call your AI feature. Supabase’s docs include a rate-limiting example for Edge Functions using Upstash Redis. Ask your builder to add a per-user limit to the function that calls your AI provider, and to require a logged-in user before it runs.
Get a second look
Prodseal’s free check looks at what any browser receives from your public URL, including keys in your JavaScript and your headers. Connect GitHub or Supabase for a free full report, which also checks for keys in your git history and AI calls with no limit. For $49 one time, Prodseal writes and tests fixes for the Critical and High issues it can fix automatically, as a GitHub pull request or as SQL plus a Lovable prompt. Anything it can’t fix automatically, such as rotating a leaked key, comes with manual steps, and nothing is merged or applied without you.
Questions go through prodseal.dev/contact.
Run my free check