Exposed API Keys in Production: How to Find and Fix Them in 2026
Every day, thousands of API keys leak into production code. Stripe secret keys in JavaScript bundles. AWS credentials in GitHub repos. OpenAI keys hardcoded in React components.
The consequences? Attackers drain your Stripe account. Mine cryptocurrency on your AWS bill. Use your OpenAI credits for their chatbots. And you won't know until the damage is done.
In this guide, you'll learn exactly how to find exposed API keys in your codebase, what to do when you discover them, and how to prevent future leaks.
Table of Contents
Why API Keys Get Exposed
API keys leak into production for surprisingly mundane reasons:
"Just testing"
A developer hardcodes a key to test an API call. They plan to move it to environment variables later. They forget.
Build process mistakes
Environment variables don't load correctly. The app breaks. Someone hardcodes the key "temporarily" to ship on time.
Copy-paste errors
Code gets copied from a tutorial or Stack Overflow. The example has a placeholder key. It never gets replaced.
Client-side confusion
Developers don't realize that anything in React, Vue, or Angular bundles is publicly visible. They treat NEXT_PUBLIC_ variables like secrets.
Git history
Keys get removed from current code but remain in commit history forever.
I've seen all of these in production apps. Including apps that passed security audits.
Common Places API Keys Hide
1. JavaScript Bundles
Your frontend code is public. Anything in bundle.js or main.chunk.js can be read by anyone:
// ❌ NEVER DO THIS
const stripe = Stripe('sk_live_51Hx7A2eZvKYlo2C...');
// ❌ ALSO VISIBLE
const OPENAI_KEY = process.env.NEXT_PUBLIC_OPENAI_KEY;
// If it starts with NEXT_PUBLIC_, it's in the bundle!2. Mobile App Binaries
Decompiling mobile apps is trivial. Keys in iOS or Android apps are public:
// ❌ Visible after decompilation
let apiKey = "AIzaSyD-9tSrke72PouQMnMX-a7eZSW0jkFMBWY"3. GitHub Repositories
Even private repos leak when:
- ▸Repository becomes public later
- ▸Team member's account gets compromised
- ▸Company gets acquired (repos transferred)
- ▸Accidental fork to public repo
4. Docker Images
Environment variables baked into Docker images:
# ❌ Key is now in the image layer
ENV STRIPE_KEY=sk_live_51Hx7A2eZvKYlo2C...5. Configuration Files
Committed .env files, config.json, or secrets.yaml:
# .env file committed to repo
STRIPE_SECRET_KEY=sk_live_51Hx7A2eZvKYlo2C...
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLEHow to Find Exposed API Keys
Manual Code Search
Search your codebase for common patterns:
# Search for common API key patterns
grep -r "api_key" .
grep -r "apikey" .
grep -r "secret" .
grep -r "sk_live" . # Stripe live keys
grep -r "sk_test" . # Stripe test keys
grep -r "AKIA" . # AWS keys
grep -r "AIza" . # Google API keysCheck Your JavaScript Bundles
- 1.Open your production site
- 2.Open DevTools (F12)
- 3.Go to Sources tab
- 4.Search (Ctrl/Cmd + Shift + F) for:
api_key,secret,token
If you find anything suspicious, it's exposed.
Automated Scanning Tools
TruffleHog (Free, open source)
docker run --rm -v $(pwd):/repo trufflesecurity/trufflehog \
filesystem /repo --jsonGitleaks (Free, open source)
brew install gitleaks
gitleaks detect --source . --verboseCyberChecker (Paid, $39)
Scans your live production site for exposed secrets in client-side code. Takes 60 seconds, shows exact locations.
What Happens When Keys Are Exposed
The damage depends on what the key can access:
Stripe Keys
Exposed secret key: Attackers can refund all transactions, access customer data, create payouts to their accounts
Real case: Company lost $40,000 in fraudulent refunds
AWS Keys
Exposed access key: Spin up EC2 instances for crypto mining, access S3 buckets, delete databases
Real case: $50,000 AWS bill from crypto mining in 48 hours
OpenAI Keys
Exposed API key: Use your credits for their applications, rack up massive bills
Real case: $8,000 in API costs over a weekend
Database Credentials
Exposed connection string: Full database access, data theft, ransomware
Real case: Entire customer database sold on dark web
Real-world breaches have cost companies millions. The average data breach costs $4.45 million according to IBM's 2023 report. Many start with exposed API keys.
Step-by-Step Fix Guide
⚡ Immediate Actions (Do This First)
1Revoke the exposed key immediately
Don't wait. Don't investigate first. Revoke now:
- ▸ Stripe: Dashboard → Developers → API Keys → Roll key
- ▸ AWS: IAM → Users → Security Credentials → Make inactive
- ▸ OpenAI: API Keys → Revoke
- ▸ GitHub: Settings → Developer Settings → Revoke token
2Generate a new key
Create a replacement key before removing the old one from your code.
3Update your code
Move the key to environment variables:
// ✅ Server-side only (Next.js API route)
export default async function handler(req, res) {
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
// This code runs on server, key never sent to client
}4Deploy the fix
Push updated code to production immediately.
5Monitor for abuse
Check for:
- ▸ Unusual API usage spikes
- ▸ Unexpected charges
- ▸ Failed authentication attempts
- ▸ Data access logs
Remove from Git History
Just deleting the key from current code isn't enough. It's still in git history:
# Install BFG Repo Cleaner
brew install bfg
# Remove all instances of the exposed key
bfg --replace-text passwords.txt
# Clean git history
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# Force push (WARNING: Coordinate with team first)
git push origin --force --allAlternative: If you can't rewrite history (shared repo), at least revoke the key so the historical reference is useless.
Prevention Strategies
1. Use Environment Variables Correctly
Server-side (Node.js, Next.js API routes):
// ✅ Safe - runs on server only
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);Never use NEXT_PUBLIC_ for secrets:
// ❌ EXPOSED - NEXT_PUBLIC_ vars go to browser
const key = process.env.NEXT_PUBLIC_STRIPE_SECRET;2. Add .env to .gitignore
# .gitignore
.env
.env.local
.env.production
.env.*.localProvide a template instead:
# .env.example (commit this)
STRIPE_SECRET_KEY=sk_live_your_key_here
AWS_ACCESS_KEY_ID=your_key_here3. Implement Key Rotation
Rotate API keys regularly:
- ▸Every 90 days for production keys
- ▸Immediately after team member leaves
- ▸After any suspected compromise
4. Monitor API Usage
Set up alerts for:
- ▸Unusual request volumes
- ▸Requests from unexpected IPs/locations
- ▸Multiple failed auth attempts
- ▸API calls outside business hours
Real-World Examples
The scale of API key exposure is staggering. Security researchers regularly find thousands of exposed keys:
Security researchers have discovered massive API key databases exposed online, affecting millions of applications. These breaches highlight how critical proper key management is.
Case Study: Uber 2016 Breach
What happened: Uber engineers committed AWS keys to a private GitHub repo. Attackers found the keys and accessed 57 million user records.
Damage: $148 million settlement, loss of customer trust, regulatory investigations.
Lesson: Private repos aren't safe. Use secret management tools.
Case Study: Cryptocurrency Mining Attack
What happened: A startup left AWS keys in their React app's bundle. Attackers spun up 300 EC2 instances to mine Bitcoin.
Damage: $73,000 AWS bill in 3 days.
Lesson: Never put AWS keys in client-side code. Ever.
Case Study: Startup Database Leak
What happened: Supabase anon key exposed in Next.js app with no Row Level Security policies. Competitor scraped their entire user database.
Damage: Lost competitive advantage, 40% customer churn after breach disclosure.
Lesson: Supabase anon keys are meant to be public, but only if you have RLS enabled.
Frequently Asked Questions
How do I know if my API keys are already exposed?
Search your production JavaScript bundles using browser DevTools. Check your git history with tools like TruffleHog or Gitleaks. Scan your live site with automated tools like CyberChecker that specifically check for exposed secrets in client-side code.
Are Supabase anon keys supposed to be public?
Yes, but only if you have Row Level Security (RLS) policies enabled on all tables. The anon key is meant for client-side use, but RLS ensures users can only access data they're authorized to see. Without RLS, exposing the anon key means anyone can read/write your entire database.
Can I use API keys in mobile apps?
No secure way exists to hide keys in mobile apps—they can always be decompiled. Instead, have your app authenticate users with your backend, then make API calls server-side using keys stored securely there.
What's the difference between NEXT_PUBLIC_ and regular env vars?
Variables prefixed with NEXT_PUBLIC_ are embedded in the JavaScript bundle and sent to the browser. Regular environment variables (without the prefix) are only available server-side. Never use NEXT_PUBLIC_ for secrets.
How often should I rotate API keys?
Rotate production keys every 90 days at minimum. Rotate immediately if a team member with access leaves, if you suspect a compromise, or after any security incident.
Conclusion
Exposed API keys are one of the most common and costly security vulnerabilities. They're easy to create accidentally and expensive to fix after the damage is done.
The good news: prevention is straightforward. Use environment variables correctly. Never commit secrets to git. Scan your code regularly. Rotate keys periodically.
Take action now:
- 1.Scan your production site for exposed secrets (use browser DevTools or automated tools)
- 2.Check your git history with TruffleHog or Gitleaks
- 3.Set up pre-commit hooks to catch future leaks
- 4.Educate your team on proper key management
Don't wait for a breach to take security seriously. One exposed Stripe key can cost more than every security tool combined.
Need help finding exposed secrets in your production app?
Scan your site in 60 seconds to see if you have exposed API keys, database credentials, or other security issues.
Scan Your Site Now - FreePublished by CyberChecker Security Team
Last updated: