Guides

Guide · Leaked keys and files

Your secret keys are in your app’s JavaScript

Everything your app’s JavaScript contains, anyone can read. Open the site, open the browser’s developer tools, and it’s all there, keys included. A secret key in that code is a key you’ve handed to every visitor.

Why it matters

A secret key lets whoever holds it act as you: charge cards through Stripe, run up an OpenAI or Anthropic bill, send email from your account. Enrichlead, a SaaS built with Cursor in public, had its API keys readable in the browser, and people reportedly used the console to get around its paywall (Indie Hackers). In a scan of about 5,600 public apps built with AI tools, Escape found 400+ exposed secrets (Escape, a security vendor).

Public keys and secret keys

Stripe publishable keypk_live_…Public is fine
Supabase anon or publishable keySafe only with Row Level Security on.Public is fine
Firebase or Maps browser keyRestrict it to your domain in Google Cloud.Public is fine
Stripe secret or restricted keysk_live_…, rk_live_…Server only
OpenAI, Anthropic and OpenRouter keyssk-proj-…, sk-ant-…, sk-or-v1-…Server only
Supabase service_role or secret keysb_secret_…Server only
AWS, GitHub, SendGrid and Slack keys, private keysServer only

A common way secrets get in: a variable named VITE_… (or NEXT_PUBLIC_… in Next.js) is copied into the browser code on purpose. That prefix means “this is public”, so putting a secret key in one publishes it (Vite docs).

See it yourself

  1. Open your live site in Chrome, Edge or Firefox and open the developer tools (F12, or right-click › Inspect).
  2. Press Ctrl+Shift+F (Cmd+Option+F on a Mac) to search every file the page loaded.
  3. Search for sk_live, sk-proj, sk-ant, service_role and sb_secret. Any match is a key a stranger can copy.

Fix it

First, rotate the key in the provider’s dashboard: make a new one and delete the old one. Removing a key from your code doesn’t un-leak it, because copies may already exist. Then move every call that needs a secret to a server function, so only your server holds the key. This is the same prompt our checker gives you:

Paste this into Lovable, Bolt, Cursor or Claude Code

Secret keys are visible in my app’s public JavaScript. 1) Find every place in my code that uses a secret key in the browser. 2) Move each call that needs a secret into a server-side function (an API route or edge function) so the browser never sees the key. 3) Remind me to rotate each exposed key in its provider’s dashboard, because removing it from the code doesn’t un-leak it.

What this can’t tell you

We read the JavaScript your page loads, up to five of your own files. Keys in files that only load after sign-in, in your server code, or in your repository’s history, we can’t see. A clean result means the public code we read has no secret keys, not that none exist anywhere.

Related

Sources