Exposed API Keys in Front-End Code: Find and Rotate Them

Any key shipped to the browser is public. Learn which keys can live in front-end code, how to find leaked secrets with Gitleaks, and how to rotate them fast.

Short answer: Any API key that ends up in your front-end bundle is public, because anyone can open the browser's developer tools and read it. Find leaked keys with a secret scanner such as Gitleaks, move them behind a server-side function, and rotate every exposed key right away, even if you are not sure anyone saw it.

Why front-end keys are public

Everything your app sends to the browser can be read by the person using it: JavaScript files, source maps, network requests and environment values baked in at build time. Hiding a key in a variable name or minifying the bundle does not change that.

Build tools make this easy to miss. The Vite documentation states that variables prefixed with VITE_ "will be exposed in client-side source code after Vite bundling," and that they "should not contain sensitive information such as API keys." If your app is built on Vite, the prefix is tempting because it makes a value work in the browser immediately. That convenience is the leak.

Wiz Research reported finding third-party API keys and service account credentials hardcoded into client-side JavaScript of vibe-coded apps. The problem is growing: GitGuardian counted 1,275,105 leaked secrets tied to AI services on public GitHub in 2025, up 81% from 2024, and leaked Supabase keys rose 992%, according to The Hacker News.

Which keys can live in the browser

Not every key is a secret. Some are designed to be public and are protected by other controls.

Key typeCan it be in front-end code?What protects it
Stripe publishable key (pk_...)YesDesigned for client-side use, per Stripe
Stripe secret or restricted key (sk_..., rk_...)NoMust stay on a server
Supabase anon/publishable keyYesRow-level security policies
Supabase service role keyNoBypasses row-level security entirely
OpenAI, Anthropic and other model API keysNoBilling is tied to the key
Maps or analytics keys with domain restrictionsUsuallyReferrer or domain allowlists
Database passwords, SMTP credentials, webhook signing secretsNoMust stay on a server

Stripe's key guidance is explicit: secret keys "must stay in your server environment," and client-side apps should embed publishable keys instead. The Supabase anon key is only acceptable in the browser if row-level security is on for every table. See The Supabase RLS mistake.

How to find exposed keys

Check three places: your repository, your git history and your live site.

1. Scan the repository and its history. Gitleaks is a free, MIT-licensed scanner that checks the working tree and full git history for API keys, access credentials and passwords:

gitleaks git -v .

History matters. A key you deleted last month is still readable in old commits, and on a public repo it may already have been copied.

2. Search the built bundle. Run your production build, then search the output folder for common key prefixes:

grep -rE "sk_live|sk_test|sk-|service_role|AKIA" dist/

3. Look at the live site. Open your deployed app, open the browser's developer tools, and search the Sources and Network tabs for key-like strings. This is exactly what an attacker does.

You can also run your deployed app through the GreenGo checker. It is an automated scan, not a security audit.

How to rotate a leaked key

The OWASP Secrets Management Cheat Sheet lays out the response in order: revoke, rotate, delete, then log and investigate. In practice:

  1. Revoke or roll the key in the provider's dashboard. Stripe, Supabase, OpenAI and most other services let you create a new key and expire the old one. Stripe says to rotate an exposed key "immediately even if you aren't sure anyone saw it."
  2. Store the new key server-side. Put it in your platform's secrets store (Supabase Edge Function secrets, Vercel or Netlify environment variables without a public prefix, or a vault).
  3. Move the API call to the server. Instead of calling the provider from the browser, call your own backend function, which reads the key at runtime and forwards the request. Wiz recommends this proxy pattern for vibe-coded apps.
  4. Remove the old key from code. Delete it from the current files. Rewriting git history is optional and has side effects, and it does not help once a key has leaked, which is why rotation comes first.
  5. Check usage logs. Look at the provider's request logs and billing for activity you don't recognize.
  6. Add a guardrail. Set up a pre-commit hook or CI step with Gitleaks so the same mistake fails the build next time. Both OWASP and Stripe recommend scanning before code is committed.

Prompting your AI tool to avoid this

Most leaks start with a prompt like "connect to OpenAI." A more specific instruction helps:

  • "Call the OpenAI API from a server-side function. Read the key from a secret, never from client code."
  • "Do not use the VITE_ prefix for any API key."
  • "Use only the Stripe publishable key in the front end. Create the checkout session on the server."

Review the diff afterward and confirm the tool actually followed them.

Why buyers care

If you plan to sell your app, a key in the bundle is one of the first things a technical buyer will find. It also complicates handover: every key has to be rotated and moved into the buyer's accounts anyway.

On GreenGo, the Green Light badge includes a Gitleaks secrets check alongside DNS ownership, headers, dependency and delivery-file checks. It shows the check date, lasts 90 days, and is not a security audit or certification. When your app passes, list it on /sell. Listing is free.

Sources

Updated October 26, 2026.

Questions & answers