← Back to all resources
Guide

Did the AI put your API keys in the wrong place? How to check and what to rotate

By Seth Tucker · Updated June 2026

Open your app in a browser. Right-click anywhere, choose Inspect, click the Network tab, reload the page, and use the app normally for 30 seconds. Search the requests that appear for the strings "key," "token," "secret," "sk-," "pk_live," or "anon." If you find a key that is not the Supabase anonymous (public) key, stop what you are doing and rotate it at its source before continuing. That is the check. This article explains what to rotate and where.

Why this is the highest-priority check

An API key is a credential. When a key for a paid service — OpenAI, Stripe, Twilio, SendGrid — ends up in the browser, anyone who opens developer tools can read it. From that point, the key can be used by anyone for anything that service allows: generating AI content at your expense, charging your Stripe account, sending SMS messages, forwarding email. Automated scanners harvest exposed credentials continuously.

A founder publicly reported that exposed Stripe keys in his vibe-coded app led to 175 customers being charged $500 each and $2,500 in Stripe fees. The key had been placed in the frontend. Rotation would have cost nothing. The exposure cost significantly more.

Lovable's own security guide advises founders to verify that third-party API keys are called server-side and are not present in the frontend bundle. Replit's documentation warns that hardcoded secrets can leak through public apps, GitHub, copy-paste, screen sharing, or streaming. OWASP's Secrets Management guidance emphasizes limiting access and actively monitoring secret use.

Publishable vs secret keys: which ones can be in the browser

Not all keys are equal. Some are designed to be public. Most are not.

Key typeCan it be in the browser?What happens if it leaks
Supabase anon / public keyYes — by design; this is how the frontend communicates with the databaseSafe to be public only when Row Level Security is enabled and correctly configured on your tables. Without RLS, anyone with this key can query your entire database.
Stripe publishable key (pk_live_... or pk_test_...)Yes — this is designed for frontend use; it can only create tokens, not chargesLow risk on its own; however, your Stripe secret key must never be in the browser
Supabase service-role keyNo — must only be used in server-side codeAnyone with this key has full admin access to your database, bypassing all Row Level Security
Stripe secret key (sk_live_... or sk_test_...)No — must only be used in server-side codeAnyone with this key can create charges, issue refunds, access customer data, and modify your Stripe account
OpenAI API key (sk-...)No — must only be used in server-side codeAnyone with this key can make API calls billed to your account; no spending limit means no ceiling on the cost
Anthropic API keyNo — must only be used in server-side codeSame as OpenAI
Twilio Account SID + Auth TokenNo — must only be used in server-side codeAnyone with these can send SMS, make calls, and rack up charges on your account
SendGrid / Resend / Postmark API keyNo — must only be used in server-side codeAnyone with this key can send email from your domain and access your contact data
Firebase service account or admin SDK keyNoFull admin access to your Firebase project

How to check: the browser network tab walkthrough

You do not need any technical tools beyond a browser.

Step 1. Open your app. Right-click on any part of the page and select Inspect (Chrome, Edge) or Web Developer Tools (Firefox). If you are on Safari, enable the Develop menu first under Safari Preferences.

Step 2. Click the Network tab. If you see no requests, check that the "Preserve log" option is on and reload the page.

Step 3. Use the app normally: log in (if there is a login), load a page with data, trigger an AI feature, submit a form, or do anything that makes the app call its backend services.

Step 4. In the filter bar at the top of the Network tab, search for key. Look through the requests that appear for anything that looks like a long alphanumeric string in a request header, query string, or response body. Also search for token, secret, sk-, pk_live, anon, and Bearer.

Step 5. For each value you find, use the table above to determine whether it should be in the browser. If you find a Stripe secret key, an OpenAI key, a Supabase service-role key, or any credential that should not be client-side, go to the next section immediately.

What to rotate, and where

If you found a key that should not be in the browser, rotate it now. Do not move it to the right place first and rotate later. Rotate first, then move it.

Stripe secret key:

  1. Log in to the Stripe dashboard at stripe.com/dashboard.
  2. Go to Developers then API keys.
  3. Click "Roll key" next to the secret key (sk_live_... or sk_test_...). This immediately invalidates the old key.
  4. Copy the new key and place it in your server-side environment variable or your builder's secrets manager.
  5. Do not place the new key in any frontend code.

OpenAI API key:

  1. Log in at platform.openai.com.
  2. Go to API keys.
  3. Delete the exposed key and create a new one.
  4. Set a usage limit on your account if you have not already done so.

Supabase service-role key:

  1. Log in to your Supabase dashboard.
  2. Go to Project Settings then API.
  3. Click "Reveal" and then "Rotate" next to the service-role key.
  4. The old key is immediately invalidated. Copy the new key and place it only in server-side code.

Twilio Auth Token:

  1. Log in to the Twilio Console.
  2. On the dashboard, find your Auth Token and click to reveal it.
  3. Use the "Roll" option to generate a new token.
  4. Update your server-side environment with the new token.

General approach for any other key: Find the service's dashboard, navigate to API keys or credentials, delete or invalidate the exposed key, generate a new one, and place the new one only in your builder's secrets manager or your server-side environment variables — never in frontend code.

After rotating: where the key should live instead

Once you have rotated the exposed key, the new key needs to live somewhere that your app's backend can access it, without it ever appearing in the browser.

Lovable: Lovable's environment settings. The key should be referenced only by server-side functions, not by any frontend component.

Replit: The Replit Secrets tab. Reference it in server code as an environment variable (process.env.STRIPE_SECRET_KEY, for example). Do not reference it in any client-side file.

Cursor / Claude Code / a standard repository: A .env file that is listed in .gitignore and therefore never committed to your repository. A deployed environment like Railway, Fly.io, Render, or Vercel has its own secrets management where you set these values for production.

Base44: Base44's settings for server-side credentials. Review the documentation for where backend API keys are configured in your Base44 project.

What to ask an expert

If you found a key in the browser network tab and you are not sure whether it is the kind that is safe to be public or the kind that needs to be rotated, bring that question to a review conversation. The specific things worth asking:

  1. Which of the keys I can see in my app's network requests should not be there?
  2. Once I rotate them, how do I confirm the new key is only used server-side?
  3. Is there anything else in my app's code or configuration that is leaking credentials I have not found yet?
  4. Are spend limits set on my paid services so that a future exposure has a bounded cost?

If you want AgentC to walk through your app's network traffic and configuration with you, the right starting point is a demo conversation. We identify what is exposed, tell you what to rotate and where it should go, and confirm that the fix is complete.

Related guides in this series

Frequently asked questions

I rotated the key. Is my app safe now?

Rotation means the old key is invalidated — anyone who harvested it can no longer use it. But you also need to confirm that the new key is placed correctly (server-side only) and that the reason the key ended up in the browser is fixed. If the same AI-generated code still runs and still places the key in the frontend, the problem will recur the next time you deploy. Rotation is the emergency stop; fixing the placement is the actual fix.

How do I know if a key has already been used by someone else?

Check the dashboard for the affected service. Stripe shows all API requests in the Developers then Logs view. OpenAI shows usage in the Usage section of the dashboard. Twilio shows call and SMS logs. Look for requests from IP addresses that are not your servers or your own location, or for activity at times when you were not using the app. Unusual volume or unfamiliar operations are the signal.

The Supabase anon key is in my app. Should I rotate it?

The anon key is designed to be public-facing — it is expected to be in your frontend code. You do not need to rotate it. What you do need to verify is that Row Level Security is enabled and correctly configured on every table that contains user data. Without RLS, anyone with the anon key can read your entire database. With RLS configured correctly, the anon key can only access the rows that your policies permit. See How to tell if your Supabase database is exposed for the full walkthrough.

My app is not live yet. Does this matter?

Yes. Automated credential scanners do not wait for a public launch — they scan the web continuously. If your app's code has been pushed to a public GitHub repository, or if you have shared a preview link, exposed credentials can be harvested before the app officially launches. Additionally, if you push the code to a repository or deploy it to a hosting provider, the key may appear in build logs or environment configurations that are visible to more people than you intend.

How do I find keys that are hardcoded in my source code (not just in the network tab)?

If you can access your project's source code — in Lovable's code view, in your Replit project files, or in a local repository — search for the string sk-, pk_live_, service_role, and the names of the services you use (stripe, openai, twilio, sendgrid). Look in any .env file that might have been committed to a repository (check your git history). Any key found in source code that is committed or deployed should be rotated.

About this guide

Written by Seth Tucker, founder of AgentC Consulting. Seth spent approximately five years as a security engineer on election infrastructure used by roughly one in three American voters, holds SOC 2 Type 2 and ISO 27001 experience, and now helps non-technical founders and operators build, review, and trust AI-built applications.

Last updated: June 2026. Sources cited throughout reference original research, vendor documentation, and public reporting.

More than vibes

Want a second set of eyes on your app?

The right starting point is a demo conversation, not a form. We look at what you built, ask the questions that matter for your situation, and tell you plainly what is safe to ship and what needs work first.