Skip to content
SniffPup
How it worksSample reportPricingAboutDashboard

How to find exposed API keys on your website

Short answer: anything your site sends to the browser (HTML, JavaScript bundles, source maps, files left in the web root) can be read by every visitor. To find leaked keys, look at your published site the way a stranger would. You can do it by hand with the steps below, or let a scanner do it.

Fastest check: run a free SniffPup scan on your live URL. It searches your page HTML and same-origin JavaScript for secret keys (OpenAI, Anthropic, Stripe, AWS, GitHub, Slack, SendGrid, Groq, xAI, Google, Supabase service_role and secret keys, private keys and database URLs), checks for public /.env and /.git files, checks whether a source map your JavaScript points to is downloadable, and lists every issue it finds (secrets are always masked). It's passive: about 40 requests or fewer, no logins, and it never uses a secret key it finds.

1. Know which keys are allowed to be public

Some keys are made for the browser: Supabase anon or sb_publishable_ keys, Stripe pk_live_ keys and Firebase web config. Finding them is normal. Secret keys are different: Supabase service_role or sb_secret_ (they bypass Row Level Security), Stripe sk_live_ and whsec_, OpenAI sk-, Anthropic sk-ant-, AWS AKIA… with its secret, GitHub ghp_ and database URLs with a password. If any of these shows up in your frontend, treat it as leaked.

2. Search your JavaScript bundles in the browser

Open your published site (not the editor preview), open DevTools, then Sources. Press Ctrl+Shift+F (Cmd+Option+F on Mac) to search across all loaded files, and try:

  • sk-, sk-ant-, sk_live_, rk_live_, whsec_
  • service_role, sb_secret_
  • AKIA, ghp_, github_pat_, xox, SG., gsk_, xai-
  • PRIVATE KEY, postgres://, mongodb+srv://

Minifying doesn't hide a key: it stays a plain string. Also click around the app with the Network tab open and look at request headers. An Authorization: Bearer sk-… header going from the browser straight to OpenAI or Stripe means the key is in your frontend.

3. Check your build output locally

If you have the code, build it and search the output, e.g. grep -rnE "sk_live_|sk-|service_role|sb_secret_" dist/ .next/static/ build/. Any environment variable with a VITE_, NEXT_PUBLIC_ or EXPO_PUBLIC_ prefix is copied into the browser bundle by design, so never put a secret in one.

4. Try the files that shouldn't be public

Visit these on your live domain: /.env, /.env.local, /.env.production, /.git/config, /.git/HEAD and /.npmrc. A 404 is good. Lines like KEY=value or a [core] section mean the file is public. Watch out: many single-page apps return your home page for every unknown URL, which looks like a 200 but is harmless. What matters is whether the real file contents come back.

5. Check for public source maps

Open one of your .js files and add .map to the URL. If it downloads, anyone can read your original, unminified source, including comments and any values that were inlined at build time. Turn off production source maps or keep them private.

6. Check your git history too

A key you deleted can still live in old commits. Run a tool such as gitleaks or TruffleHog on your repo. An outside scanner (SniffPup included) can't see your repo.

7. If you find a secret key: rotate, then move it server-side

  1. Revoke and reissue the key at the provider right away. Deleting it from your code is not enough.
  2. Check the provider's usage or billing page for calls you didn't make.
  3. Move the call into server-side code (a Supabase Edge Function, an API route or a serverless function) that reads the key from a secret store and checks who is calling.
  4. Delete any .env or .git files from the deployed web root and redeploy.
  5. Re-scan to confirm the leak is gone.

What SniffPup checks

The scan looks at your published URL for leaked secrets (masked), public .env/.git/.npmrc/.DS_Store files (variable names only, never values), a public source map referenced by your JavaScript, security headers, cookie flags, HTTPS redirects and what AI crawlers can read. The free scan lists every issue it finds by title and severity, with full details and the fix for the most serious one. A one-time $19 Full Fix Report unlocks the explanation, evidence and copy-paste fix prompt for every finding plus 30 days of re-scans; monitoring plans start at $9/mo. See exactly what the scanner does and pricing.

FAQ

Is it safe to have my Supabase anon key or Stripe publishable key in my frontend?

Yes, those keys are designed to be public. A Supabase anon or sb_publishable_ key is only safe if Row Level Security is on for every exposed table. Secret keys such as Supabase service_role or sb_secret_, Stripe sk_live_, OpenAI sk- and AWS secret keys must never reach the browser.

I deleted the key from my code. Am I safe now?

No. If a secret key was ever public, assume someone copied it. Revoke and reissue it at the provider, then update your server-side config. Removing it from the code only stops new leaks.

Does SniffPup use the keys it finds?

No. SniffPup is passive: it pattern-matches what your published site already serves, masks any secret in the report and never uses a secret key it finds. The only key it ever sends anywhere is your public Supabase anon key, in the optional read-only Pro database check, which runs only after you verify you own the site.

Can SniffPup scan my mobile app?

No. SniffPup scans live web URLs only. If your mobile app has a web dashboard or a public website, you can scan that.

A clean report is not a guarantee of security.

Run a free scan →

SniffPup

SniffPup is a product of Ember and Saru LLC.
10850 Providence Rd #1370, Charlotte, NC 28277, USA

Support: support@sniffpup.com
Abuse & scan opt-out: abuse@sniffpup.com

ProductFree scanSample reportPricingHow our scanner worksBlog
CompanyAboutSniffPupScanner bot & opt-outsecurity.txtContact
LegalTermsPrivacyAcceptable UseRefunds

SniffPup checks what is publicly visible on your site. A clean report is not a guarantee of security. © 2026 Ember and Saru LLC