Tell Me When Down
How it worksWhat we checkPricing
BlogFree toolsCompareDocs
Log inGet started
All posts
Security for vibe-coded apps

My API key is showing on my website — is that bad?

July 18, 2026·6 min read
Antique keys scattered on black — a credential left in plain sight among many.

You opened your site's source, or the network tab, and there's an API key sitting in plain sight. First, don't panic — and don't relax either. Whether a visible key is a shrug or an emergency depends entirely on which kind of key it is.

There are two kinds of keys

This is the whole distinction, and getting it right tells you whether to close the tab or move fast:

Public keys are designed to be seen. A Supabase anon key, a Stripe pk_ publishable key, a Google Maps browser key — these are meant to live in the frontend. They're safe because something else does the protecting. Secret keys are the opposite: a Stripe sk_ secret key, a Supabase service_role key, an OpenAI key, a database URL. These grant real power and must never reach the browser.

A visible pk_ is fine. A visible sk_ is an emergency. If you can't tell which you're looking at, treat it as secret until you've confirmed otherwise — the cost of being wrong runs one direction only.

If it's a public key

You're probably fine — but "probably" has conditions. A public key is only safe because a second layer restricts what it can do, and that layer has to actually be configured:

  1. Supabase anon key: safe only if Row Level Security is on with real policies. Without RLS, that public key reads your whole database.
  2. Maps / browser keys: lock them to your domain with HTTP referrer restrictions and set usage limits, so a copied key can't rack up your bill on someone else's site.
  3. Stripe publishable key: it can only start payments, not move money — designed for the frontend.

If it's a secret key

Then it's already compromised. Not "could be" — is. Anything in the bundle has been served to every visitor and possibly indexed by bots that scan for exactly this. Deleting it from your code doesn't un-leak it. You have to:

  1. Rotate it immediately. Revoke the exposed key and issue a new one. The old value is burned.
  2. Move the new one server-side into an environment variable your frontend can't read.
  3. Call the service through a backend route so the key does its work on your server and the browser only ever sees the result.
The prefix trap: in Vite and Next.js, any env var starting with VITE_ or NEXT_PUBLIC_ is deliberately baked into the client bundle. Put a secret behind one of those prefixes and .env won't hide it — you've told the framework to ship it. Secrets get plain, un-prefixed names and stay on the server.

Triage yours in one paste

Not sure which kind you've got? This prompt tells you whether to panic and exactly what to do:

paste into Claude or ChatGPT
I found an API key visible in my website's frontend code / network tab. Help me figure out if it's dangerous and what to do. Here's the key's purpose: <WHAT THE KEY IS FOR>.

1. Tell me whether this specific kind of key is meant to be public (like a Supabase anon key, a Stripe PUBLISHABLE key pk_, a Google Maps browser key) or is a SECRET that must never ship to the browser (like a Stripe SECRET key sk_, a service_role key, an OpenAI key, a database URL, any private API key).
2. If it's a public key: explain what still protects me (e.g. RLS for Supabase, HTTP referrer/domain restrictions for map keys, usage limits) and how to lock those restrictions down so the public key can't be abused.
3. If it's a secret key: tell me it's compromised the moment it's in the bundle, and walk me through (a) ROTATING/revoking it immediately, (b) moving it to a server-side environment variable, and (c) calling the service through a backend route so the browser never sees it.
4. Explain that in Vite/Next.js, any env var prefixed with VITE_ or NEXT_PUBLIC_ is deliberately baked into the client bundle — so a secret must NOT use those prefixes.

Be direct about whether I need to panic or not.

This is one of the most common gaps in AI-generated apps — the model wires the key wherever makes the code run. It's part of the broader vibe coding security risks, and for Supabase specifically, the app-securing checklist.

After the fix

Once the key's rotated and moved, the exposure is closed — but a leaked secret often gets used before you notice, so watch for the fallout: a spiking bill, an endpoint behaving strangely, a service that suddenly goes down. Monitoring from outside catches the symptom even when the cause was a key you've already fixed.

Rotate the key, then keep an eye on the fallout.

Join Tell Me When Down free and we'll watch your app from outside — a service that goes down, an endpoint that starts erroring, uptime that drops — so if a leaked key gets abused before you caught it, you hear about the effect in minutes.

Watch my appfree · no card required
more on security for vibe-coded apps
How to secure a Supabase app: the five settings that matterA Supabase app can be wide open, almost always for the same handful of reasons: RLS off, the service_role key in the browser, public buckets, unguarded functions, secrets in the bundle. Here's the map to closing each one.Is my Supabase database public? RLS, and how to checkYour Supabase anon key is public by design — safe only if RLS is on with a real policy. Tables made outside the Table Editor ship with it off, and USING(true) is still open. Here's how to check if your data is public.Is my app built with AI safe? A non-developer's checkYou built an app with AI, it works, and you're quietly worried it's not safe — but you can't read code. Here are the four plain-English questions that matter, and how to check each one without being a developer.Is Lovable secure? The one setting that decides itA Lovable app can be wide open, and the difference is one setting most builders never touch. The anon-key/RLS model, the gap behind a 2025 CVE, and how to check yours.Is Bolt.new secure? What the generated app leaves openBolt.new builds a working full-stack app fast — which is why the security gets skipped. The usual gaps: a Supabase database with RLS off, secrets in the bundle, UI-only authorization. Here's how to audit yours.Is v0 secure? Keeping a generated Next.js app's secrets inv0's Next.js output looks production-ready, which is the trap. NEXT_PUBLIC_ bakes a var into the bundle, and a secret in a client component ships to the browser. Here's how to check a v0 app keeps its secrets in.Vibe coding security risks: the checklist nobody runsThe appeal of vibe coding is that you don't read every line — which is exactly why the holes get through. Exposed secrets, a database anyone can read, rules enforced only in the UI, and how to close each one.

spot something wrong or out of date? [email protected] — we'll fix it

Tell Me When Down

Uptime and security monitoring for people who'd rather ship than babysit servers. We watch so you can sleep.

product
How it worksWhat we checkPricingDocsBlogFAQ
free toolsWebsite security scanSupabase pause checkRender sleep checkMixed content checkerSecurity headers checkCookie security checkSSL expiry check
comparevs UptimeRobotvs Better Stackvs PingdomFor indie hackers
company
StatusAbout our botSupportPrivacyTerms
© 2026 TellMeWhenDown · tellmewhendown.com