← All guides
Critical Reported as: Secret key found in client-side JavaScript

API keys exposed in JavaScript (OpenAI, Anthropic, Stripe, AWS)

How a secret key ends up in front-end code, how to tell a secret key from a public one, and what to do the moment you find one.

Everything in your front-end bundle is public. If a secret key is in it, anyone who opens the page can copy it and use it as you. With an AI provider key that means unlimited requests billed to your account.

Secret keys and public keys

Some keys are meant to be in the browser. Reporting them would be a false alarm, so SecScan does not.

Public by design (not a leak)Secret (a finding)
Stripe pk_live_, pk_test_Stripe sk_live_, rk_live_
Supabase anon or publishable keySupabase service_role key
Firebase AIza… web API keyCloud or service-account private keys
Google Maps browser key (restrict by referrer)OpenAI sk-…, Anthropic sk-ant-…, AWS secret access key, GitHub ghp_…

A key that is public by design is never reported as a leaked secret. Some still get an Info note, titled “found in client code” and not “exposed”, so you can check that the key is restricted: a Firebase config block, a Google or Mapbox browser key, a Twilio key SID on its own. Info notes carry no weight in the grade. An AWS access key ID on its own (AKIA…) is a Low note, because it is an identifier and the secret half is what grants access; the secret access key is Critical.

How it happens

  • A build variable with a public prefix (VITE_, NEXT_PUBLIC_, REACT_APP_) holds a secret. Anything with that prefix is compiled into the bundle.
  • An AI tool calls the provider straight from the browser because that is the shortest code.
  • A key was pasted into a component while testing and never removed.

What to do

  1. Revoke the key now at the provider, then create a new one. Removing it from the code is not enough: it is already in the page you served and in any cache.
  2. Move the call to a server route (for example /api/chat) that adds the key from a server-side environment variable. The browser talks only to your route.
  3. Check the route is safe to expose: require sign-in and rate-limit it, or anyone can spend your credit through it.
  4. Rescan to confirm.

SecScan also flags the design even when no key is visible: an AI provider called directly from the browser, or a system prompt shipped in the bundle.

Last reviewed 2026-09-30