Security

How to Find and Fix API Key Leaks in Your SaaS App

In 2024, a developer exposed a Google Gemini API key in a public GitHub repo and got charged $250,000 in a single weekend. Leaked Stripe secret keys have drained accounts overnight. Here's how to find and fix these leaks before they cost you.

By AIExposureTool teamPublished on March 5, 2025Updated on May 6, 20266 min read
On this page

1How API Keys End Up in JavaScript Bundles

When you build a Next.js, React, or Vite app, your bundler (webpack, Vite, Rollup) compiles all your imports into JavaScript bundles. Any environment variable that starts with NEXT_PUBLIC_ or is referenced directly in client-side code gets included in those bundles — readable by anyone who opens DevTools.

The common mistake with AI-assisted coding

You ask Claude or ChatGPT to “add Stripe integration” and the AI generates code that uses process.env.STRIPE_SECRET_KEY in a client component. Your bundler bakes the key directly into _next/static/chunks/app.js. Everyone can read it.

2The 17 Keys We Scan For

Our security scanner checks HTML source and all JavaScript bundle files for these patterns:

Stripe secret keys (sk_live_...)
Stripe webhook secrets (whsec_...)
OpenAI API keys (sk-...)
Anthropic / Claude keys
Google Gemini keys
Supabase service role keys
Razorpay keys
AWS access keys
Twilio auth tokens
SendGrid API keys
GitHub personal access tokens
Slack bot tokens
Mailgun API keys
HubSpot API keys
Cloudflare API tokens
Intercom API keys
Braintree access tokens

Free 30-second key leak scan

Fetches all your JS bundles and matches against 17 secret patterns.

Run free scan

3How to Find Leaks Right Now

Option 1: Use our free scanner. Paste your URL at aiexposuretool.com/security. We fetch all your JS bundles and scan for all 17 patterns automatically. Results in 15 seconds.

Option 2: Manual check. Open your site in Chrome, open DevTools → Sources → look for files in _next/static/chunks/. Use Ctrl+F to search for sk_live, sk-, service_role.

4How to Fix API Key Leaks

  1. Rotate the key immediately. Go to your provider (Stripe, OpenAI, etc.) and generate a new key. Revoke the old one. Do this before anything else — assume the key has already been compromised.
  2. Move the key to server-side only. In Next.js, any variable used in a Route Handler, Server Component, or Server Action is server-side only. Never prefix secret keys with NEXT_PUBLIC_.
  3. Create a server-side API wrapper. If you need to call an external API from the frontend, create a Next.js Route Handler (/api/your-endpoint) that makes the external call server-side and returns only what the client needs.
  4. Audit your .env files. Make sure .env.local and .env.production are in your .gitignore. Run a search in your repo for sk_live or your actual key values.

5Prevent Leaks Going Forward

  • Use a secret scanning tool in CI (GitHub has native secret scanning for public repos)
  • Never use NEXT_PUBLIC_ prefix for any key that isn't safe for public consumption
  • Run our security scanner before every major release
  • Set up .env file exposure alerts — we check if your .env is publicly accessible

Pre-launch security checklist

The 5-minute audit every indie hacker should run — covers keys, headers, .env, source maps, and more.

See the checklist

Frequently Asked Questions

How do API keys end up in JavaScript bundles?

When a bundler (webpack, Vite, Rollup) compiles your imports, any environment variable prefixed NEXT_PUBLIC_ — or any value referenced directly in a client component — gets baked into the public JavaScript. Anyone with DevTools can read it. AI coding tools commonly make this mistake when generating Stripe / OpenAI / Supabase integration code.

What kinds of keys does the scanner detect?

17 patterns including: Stripe secret keys (sk_live_), Stripe webhook secrets (whsec_), OpenAI keys (sk-), Anthropic / Claude keys, Google Gemini keys, Supabase service role keys, Razorpay, AWS access keys, Twilio auth tokens, SendGrid, GitHub PATs, Slack bot tokens, Mailgun, HubSpot, Cloudflare API tokens, Intercom, Braintree.

What should I do if I find a leak?

Rotate the key IMMEDIATELY in the provider's dashboard. Don't try to remove the key from your repo first — assume it's already been scraped. Then move the key to server-side only (Route Handler, Server Component, or Server Action), refactor any client-side calls into API routes, and redeploy.

How do I check manually without a scanner?

Open your site in Chrome, open DevTools → Sources, look for files in _next/static/chunks/, then Ctrl+F search for 'sk_live', 'sk-', or 'service_role'. The scanner automates this across 17 patterns and your full bundle in 15 seconds, but a manual check works for a quick spot-test.

How can I prevent leaks going forward?

Five practices: (1) enable secret scanning in CI (GitHub has native scanning for public repos), (2) never use NEXT_PUBLIC_ for any sensitive value, (3) run a security scan before every release, (4) keep .env.local / .env.production in .gitignore, (5) set up .env exposure alerts — most scanners check if /.env is publicly accessible at the URL.

Scan your site for key leaks right now

Free. 15 seconds. Checks HTML source and all JavaScript bundles for 17 secret patterns.

Share this article

Free newsletter

AI visibility tactics, every Tuesday

One email a week — what's moving the needle in ChatGPT, Perplexity, and Gemini. No fluff, no spam.

Join founders building visibility in AI search. Unsubscribe anytime.

AI

Track your visibility

See if ChatGPT recommends you — in 60s

Free 25-signal scan + auto-generated llms.txt, JSON-LD, and FAQ schema. No card required.

Run free audit

Used by 1,000+ teams to improve AI search visibility.