Leaked API keys in vibe-coded apps
If your repo is public and a key was ever committed, treat it as a leaked API key, even if you deleted it later. Bots scan public GitHub repos for secrets all the time. GitHub counted more than 39 million leaked secrets across the platform in 2024. Here's how keys leak in AI-built apps and what to do, in order.
QUICK CHECKLIST
- Rotate the key in the provider's dashboard first
- Check the provider's usage and billing for strange calls
- Move the key into an environment variable
- Add .env to .gitignore
- Scan the full git history with gitleaks
How a leaked API key ends up public
- The AI puts the key directly in
config.js"for now". .envisn't in.gitignore, so the firstgit add .commits it.- A key is deleted in the latest commit but still sits in git history, where anyone can read it.
- Frontend code ships a secret key to every browser, often through a
VITE_orNEXT_PUBLIC_variable.
Hardcoded keys are one of the AI-generated code security risks we see most.
What to do when an API key leaked
Rotate the key
Create a new key in the provider's dashboard and revoke the old one. Do this first. The old key stays usable until you revoke it.
Check what it was used for
Look at the provider's usage, logs and billing for calls you didn't make. For cloud and payment keys, check for new resources or payouts.
Move it to an environment variable
Read the key with
process.env(or your framework's server-only env) and keep the value out of the code.Ignore .env
Add
.envto.gitignoreand commit a.env.examplewith placeholder values.Scan the whole history
Run
gitleaks git(older versions:gitleaks detect) on the repo to find every secret in every commit, not just the latest.Rewrite history only if you need to
GitHub's docs explain how to remove secrets from git history with
git filter-repo. It's optional once the key is rotated, and it doesn't remove copies people already cloned.
Before and after
// src/config.js
export const openai = new OpenAI({
apiKey: "sk-proj-...",
})// src/config.js (server only)
export const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
})
# .gitignore
.envFix prompt you can paste
Find every hardcoded API key or secret in this repo. Move each one to an environment variable, add .env to .gitignore, create .env.example with placeholders, and list which keys I must rotate.
How Leakcade checks this
We run gitleaks on your files and on recent git history, so a key that was "deleted" later still shows up. Keys appear only partly masked in your report. We also flag secret-looking variables with a public prefix, which ship to the browser even when they never reach git.
Further reading
- GitHub blog: 39M secret leaks in 2024
- GitHub docs: Remediating a leaked secret
- GitHub docs: Removing sensitive data from a repository
- gitleaks on GitHub
FAQ
Is deleting the key from my code enough?
No. The old commit still contains it, and bots may have copied it already. Rotate the key in the provider's dashboard, then clean up the code.
Do I have to rewrite my git history?
Not if the key is rotated. A revoked key in history is useless. Rewriting history with git filter-repo is worth it for secrets you can't rotate, like personal data, and it won't remove existing clones or forks.
Does GitHub detect leaked keys?
Partly. GitHub secret scanning tells many providers (like AWS and OpenAI) when their keys show up in public code, and push protection is on by default for public repos. It doesn't know every key format, so scan yourself too.
Is it safe to commit .env.example?
Yes, as long as it only has placeholder values. It shows other developers which variables they need without giving away yours.
Want a second pair of eyes?
We review your whole repo and write a fix prompt for every finding. $19, report within an hour.
Check my repoLeakcade is an automated check. It can miss vulnerabilities and is not a substitute for a professional security audit or pentest. Provided as is. You stay responsible for your code. Where the law allows, our liability is limited to what you paid ($19). Terms