TL;DR
Exposed API keys happen when secret credentials end up in public places like GitHub repos, frontend JavaScript, or browser network requests. Attackers find these keys within minutes using automated bots. The fix is simple: move keys to environment variables and never commit them to version control. If a key is already exposed, rotate it immediately.
$50,000+ Average cost when AWS keys are exposed and abused for crypto mining Source: GitGuardian State of Secrets Sprawl 2024
What Are Exposed API Keys?
An API key is like a password that lets your application access external services. When you use Stripe for payments, OpenAI for AI features, or AWS for cloud services, you get API keys to authenticate your requests.
Exposed API keys happen when those credentials become visible to people who shouldn't have them:
- Committed to Git: Keys pushed to public (or even private) repositories
- Hardcoded in frontend: Keys visible in JavaScript that runs in the browser
- Visible in network requests: Keys sent in URLs or headers that anyone can see
- Logged to consoles: Keys printed in error messages or debug output
- Included in build artifacts: Keys bundled into compiled code
Why This Is the #1 Vibe Coding Issue
AI coding assistants are trained on public code, which often includes examples with placeholder API keys. When you ask an AI to integrate Stripe or OpenAI, it generates code with hardcoded values:
// This is what Cursor, Bolt, or Copilot might produce
const stripe = require('stripe')('sk_live_abc123xyz789');
const openai = new OpenAI({ apiKey: 'sk-proj-abcdef123456' });
If you ship this to production or push it to GitHub, your keys are exposed. Bots scan for these patterns constantly and will find them within minutes. Sometimes seconds.
Real impact: GitGuardian detected over 12.8 million new secrets exposed in public GitHub repositories in 2023 alone. Many belong to vibe coders who didn't realize their AI-generated code contained real credentials.
How Attackers Find Exposed Keys
Automated Scanning
Attackers run bots against GitHub's public event stream, watching for new commits in real time. The bots match known API key patterns, scan website JavaScript, and trawl network request logs. You don't need to be a high-profile target. Volume is the point.
Key Patterns They Look For
| Service | Key Pattern | What Attackers Do |
|---|---|---|
| AWS | AKIA... (20 chars) | Spin up crypto miners, access S3 buckets |
| Stripe | sklive... | Issue refunds, access customer data |
| OpenAI | sk-... | Run up massive API bills |
| Twilio | SK... (32 chars) | Send spam SMS, phishing calls |
| SendGrid | SG.... | Send spam and phishing emails |
Common Places Keys Get Exposed
1. Frontend JavaScript
// In your React component
const response = await fetch('https://api.openai.com/v1/chat', {
headers: {
'Authorization': 'Bearer sk-proj-your-secret-key' // Visible to everyone!
}
});
2. Git History
Even if you remove a key from your current code, it still exists in your Git history:
# This command shows all previous versions of a file
git log -p --all -S 'sk_live' -- .
# Attackers can find keys you "removed" months ago
3. Environment Files Committed
# This should NEVER be in your repo
STRIPE_SECRET_KEY=sk_live_abc123
DATABASE_URL=postgres://user:password@host/db
OPENAI_API_KEY=sk-proj-xyz789
4. Build Artifacts and Logs
// Debug logging that exposes keys
console.log('Config:', config); // Prints all keys to console
console.log('Request headers:', headers); // Includes auth tokens
How to Fix Exposed API Keys
Step 1: Use Environment Variables
// Server-side code
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// Never hardcode keys directly!
Step 2: Configure .gitignore
# Environment files
.env
.env.local
.env.*.local
.env.production
# IDE and system files
.idea/
.vscode/
.DS_Store
Step 3: Use Backend for Sensitive API Calls
// Frontend calls YOUR backend
const response = await fetch('/api/generate-text', {
method: 'POST',
body: JSON.stringify({ prompt: userInput })
});
// Backend (server-side) calls OpenAI with the secret key
// app/api/generate-text/route.ts
export async function POST(req) {
const { prompt } = await req.json();
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }]
});
return Response.json(response);
}
Step 4: Rotate Exposed Keys Immediately
If a key's already out there, you can't unexpose it. Do this now:
- Generate a new key in your service provider's dashboard
- Update your app to use the new key and deploy
- Delete or revoke the old key
- Review your billing and logs for unauthorized usage
Pro tip: Many services (GitHub, GitLab, AWS) offer secret scanning that automatically detects and alerts you when keys are committed. Enable these features.
Platform-Specific Guidance
| Platform | Where to Store Keys | Documentation |
|---|---|---|
| Vercel | Project Settings > Environment Variables | vercel.com/docs/environment-variables |
| Netlify | Site Settings > Environment Variables | docs.netlify.com/environment-variables |
| Railway | Project > Variables | docs.railway.app/develop/variables |
| Replit | Secrets tab (lock icon) | docs.replit.com/programming-ide/secrets |
What Keys Are Safe in Frontend?
Some keys are designed to be public. These are actually safe to ship in the browser:
- Stripe Publishable Key (
pk_live_...) - Designed for browser use - Firebase Config - Public by design, secured by rules
- Supabase Anon Key - Public, protected by Row Level Security
- Google Maps API Key - Public, but restrict by domain
Even "public" keys aren't unconditional. Set domain restrictions and API quotas. If usage spikes, you'll want an alert before the bill does.
What happens if my API key is exposed?
Attackers can use your API key to make requests on your behalf. This typically results in unexpected charges (sometimes thousands of dollars), data theft, or abuse of services like sending spam through your email API.
How do attackers find exposed API keys?
Bots continuously scan GitHub, GitLab, and public websites for patterns that match API keys. They check browser developer tools, JavaScript source code, and public repositories. Once found, keys are often exploited within minutes.
Can I undo an exposed API key?
You cannot undo the exposure, but you can mitigate damage by immediately rotating (replacing) the key. Go to your service provider's dashboard, generate a new key, update your application to use the new key, then delete the old one.
How do I remove a key from Git history?
You can use tools like git-filter-repo or BFG Repo Cleaner to rewrite history and remove secrets. However, if the repo was ever public, assume the key is compromised and rotate it regardless.
Check Your App for Exposed Keys
Our scanner finds API keys in your code, Git history, and deployed app.