Google API key exposed in your frontend: is it a leak, and how do you lock it down?
You opened DevTools on your live app, or a scanner flagged it, and there it is: a string starting with AIza sitting in your JavaScript. Maybe Lovable, Bolt, Cursor or Google AI Studio put it there for a map, for Firebase sign-in, or for Gemini.
Short answer: it depends on what the key is allowed to do. Firebase web config keys and Google Maps JavaScript keys are meant to sit in the browser, but only if they're restricted. A key that can call Gemini (the Generative Language API) must never be in frontend code. An unrestricted key in the browser is a leak.
- Firebase web config keys and Google Maps JavaScript keys are meant to sit in the browser. They're safe only if they're restricted: limited to the APIs they need, and for Maps, to your website.
- A key that can call Gemini (the Generative Language API) must never be in frontend code. Anyone who copies it can spend your quota and, per Google, reach resources in your project.
- An unrestricted key in the browser is a leak. Google says plainly that you are financially responsible for charges caused by abuse of unrestricted API keys.
All Google API keys look alike (AIza + 35 characters), so you can't tell from the string which kind you have. Here's how to tell, and how to fix each case.
Step 1: Find every Google key your live app ships
Do this on the deployed site, not in your editor. What matters is what visitors download.
- Open your live app in Chrome, logged out.
- DevTools → Network → filter JS → reload.
- Press Ctrl+Shift+F (Cmd+Option+F on Mac) and search
AIza. - Note each distinct key and which file it's in.
Then search your project for where it comes from. In Vite apps (Lovable, Bolt) anything named VITE_... is bundled into the browser. In Next.js it's anything named NEXT_PUBLIC_.... A VITE_GEMINI_API_KEY or NEXT_PUBLIC_GOOGLE_AI_KEY is a red flag by name alone. (More on this: Vite env variables exposed, NEXT_PUBLIC_ variables exposed.)
Step 2: Find out what each key can do
Open Google Cloud console → APIs & Services → Credentials and select the project. For each key you found:
- Name. Firebase auto-creates keys named like
Browser key (auto created by Firebase). A key namedGemini API KeyorGemini Developer API key (auto created by Firebase)is a Gemini key. - API restrictions. Is it "Don't restrict key", or a list of APIs? Per Firebase's docs, an unrestricted key "can be used to access any API that is enabled for the project". That includes Gemini, if Gemini is enabled.
- Application restrictions. Is it limited to your website's address?
| What you find | Public by design? | What to do |
|---|---|---|
| Firebase browser key, API list holds only Firebase APIs, no Generative Language API | Yes. Firebase says these keys "do not need to be treated as secrets" when set up this way | Keep it. Make sure Firebase Security Rules and App Check protect your data. The key doesn't. |
| Maps JavaScript API key with a Websites restriction (your domain) and an API list holding only the Maps APIs you use | Yes, that's how Maps JS is meant to work | Keep it. Add quotas. Use separate keys per app. |
| Any key set to Don't restrict key | No | Restrict it now (Step 3). If it has been public for a while, check usage, then rotate. |
| Any key whose API list includes Generative Language API (Gemini) | No, never | Treat it as leaked: create a new server-side key, switch the app, then disable the old one (Step 4). |
| A Maps web service key (Geocoding, Places, Routes called directly from the browser) | No. Google says web service keys "are not expected to be publicly exposed" | Move those calls behind a server or proxy, and give the server key an IP restriction. |
Why Gemini changed the rules
For years Google told developers that Maps and Firebase keys weren't secrets. In February 2026, Truffle Security reported (Google API keys weren't secrets, but then Gemini changed the rules) that when the Gemini API is enabled on a project, existing unrestricted keys in that project, including old Maps keys sitting in public HTML, could call Gemini too. That opened uploaded files and cached content, and billed the owner for usage.
Google has since tightened things. As of today (checked Oct 22, 2026), the Gemini API docs say:
- new keys created in Google AI Studio since May 28, 2026 are "authorization keys", restricted to the Gemini API by default;
- the Gemini API rejects requests from unrestricted standard keys.
That helps, but it doesn't make a Gemini-capable key safe in a browser. A key that's restricted to Gemini still works for anyone who copies it. Google's rule is unchanged: "Never expose keys client-side in production."
Google AI Studio apps
Per Google's docs, AI Studio's Build mode now keeps GEMINI_API_KEY as a server-side secret. Apps built before May 14, 2026 are upgraded to the server-side setup the next time you change their Gemini features. If you exported or deployed an older AI Studio app elsewhere, check its bundle (Step 1). An older client-side setup may still be shipping the key.
Step 3: Lock down keys that are meant to be public
In APIs & Services → Credentials → (your key):
- Application restrictions → Websites. Add your production domain, e.g.
https://yourapp.com. Addhttps://*.yourapp.comonly if you use subdomains. Remember preview URLs (*.lovable.app,*.vercel.app) if you need them, and remove them when you don't. - API restrictions → Restrict key. Tick only the APIs this key needs, such as Maps JavaScript API and Places API (New). For a Firebase key, keep only the Firebase APIs Firebase lists. Never tick Generative Language API on a browser key.
- Quotas. In the console, lower per-day or per-minute quotas for each API to what your app really uses.
- Budget alerts. In Billing → Budgets & alerts, set an alert on the project. These are Google's alerts, and they notify you. They don't stop spending by themselves.
- Disable APIs you don't use on the project. Per Google's Maps guidance, a disabled API can't be abused through any key.
Website restrictions stop other websites from using your key in a browser. They're not a lock against someone calling the API directly with a forged header. So the API list matters most: a public key should only be able to do public things.
Step 4: If a Gemini (or other paid) key was public, rotate it
Follow Google's own leak checklist, in this order:
- Create a replacement key in Google AI Studio or Cloud console, and keep it server-side only: a Supabase Edge Function secret, a Vercel/Netlify server function, Replit Secrets used by server code, or AI Studio's Secrets panel.
- Change the app so the browser calls your endpoint, and your endpoint calls Gemini. Require a signed-in user on that endpoint, and rate-limit it.
- Deploy, then confirm the old key is gone from the live bundle (Step 1 again).
- Disable, then delete, the old key in Cloud console once the new one works.
- Check usage and billing in Cloud console for activity you don't recognize.
Deleting the key from your code doesn't un-leak it. Old deploys, caches and git history still have it. Revoking it at Google is what kills it. Full order of operations: Rotate a leaked API key.
Fix prompt for Lovable, Bolt or Cursor
My app calls the Gemini API from the browser using a key in a VITE_ / NEXT_PUBLIC_ variable. Move every Gemini call into a server-side function (Supabase Edge Function / API route). Read the key from a server secret named GEMINI_API_KEY, never from a client env var. The browser should call my function, which checks the user is signed in, then calls Gemini. Remove the old client env var and every reference to it. Show me the diff and list each file that still contains "AIza" after the change.
For a Maps or Firebase key, you usually don't need code changes, just the console restrictions in Step 3.
What the free ShipWatch scan checks here (and what it doesn't)
- It does: read your live page's HTML and up to 25 JavaScript files the page links to, and flag Google API keys (
AIza...), along with Stripe, OpenAI, Anthropic, AWS and Supabase secret or service_role keys. Keys are shown masked. It also checks for a public/.envand/.git/HEAD, HTTPS, and four security headers. - It doesn't: sign in to your Google Cloud project. So it can't see whether a key is restricted or which APIs are enabled. That's Step 2, and only you can do it. It doesn't test Firebase Security Rules or any database, and it doesn't scan pages or scripts your homepage doesn't link to.
So a flagged AIza key isn't automatically an emergency. It's a prompt to do Step 2 in the console. A clean scan isn't a guarantee either.
Run the free scan on your live app → (only scan apps you own)
Checked against Google's documentation (Firebase API keys, API keys are open secrets) on Oct 22, 2026. Google changes key behavior often (the Gemini key changes rolled out through 2026), so recheck the linked docs before relying on any date here.
FAQ
- Is a Google Maps API key in my frontend a leak?
- Not by itself. The Maps JavaScript API is designed to run with the key in the page. It becomes a problem when the key is unrestricted, can call APIs beyond Maps, or isn't limited to your website. Restrict it (Step 3) and set quotas.
- Is my Firebase apiKey a secret?
- Per Firebase's docs, no, as long as it's used only for Firebase services, restricted to Firebase APIs, and doesn't include the Generative Language API. Your data is protected by Firebase Security Rules and App Check, not by hiding the key.
- Can I call Gemini directly from the browser if I restrict the key to my domain?
- Google's guidance is no: "Never expose keys client-side in production." Use a backend proxy, or Firebase AI Logic with App Check, which Google describes as calling Gemini without embedding a raw key.
- Will a scanner tell me if my key is restricted?
- Not an outside-in one like ShipWatch. Restrictions live in your Google Cloud project, which no outside scanner can see. Check them in APIs & Services → Credentials.
- Google emailed me about a "publicly accessible Google API key". What now?
- Firebase's docs cover this: if it's your Firebase browser key, restricted to Firebase APIs and without Generative Language API, it can stay public. Any other key in that email should be restricted, or rotated if it can reach paid APIs.
- Do I need to rotate a Maps key that was unrestricted?
- Google's Maps guidance is to restrict first, and rotate only if you see unauthorized use you can't stop with restrictions. A key that can call Gemini or other paid AI APIs should be rotated.