Guides / How to find and rotate exposed API keys in a Cursor or Claude Code app
How to find and rotate exposed API keys in a Cursor or Claude Code app
AI coding agents read your files and happily paste keys into code. Here is how to find what leaked, rotate it in the right order, and stop it happening again.
1. Find out where keys can leak
There are three places to look, in order of how public they are:
- Your live JS bundle. Anything with
NEXT_PUBLIC_(Next.js) orVITE_(Vite) is inlined into browser JavaScript at build time. Both frameworks' docs say so explicitly. - Your git history, including commits you later "fixed". Deleting the line does not remove the old commit.
- Your working tree:
.envfiles, config files, test scripts.
2. Search for common key shapes
From your repo root, search the current files and the full history:
# current files (ripgrep)
rg -n --hidden -g '!node_modules' -e 'sk_live_' -e 'sb_secret_' -e 'service_role' -e 'sk-ant-' -e 'sk-proj-' -e 'AKIA[0-9A-Z]{16}' -e 'ghp_'
# every commit ever
git log -p --all | rg -n -e 'sk_live_' -e 'sb_secret_' -e 'service_role' -e 'sk-ant-' -e 'sk-proj-' -e 'AKIA[0-9A-Z]{16}' -e 'ghp_'
Then open your deployed site, open DevTools, and search the loaded JS for the same strings. If it is in the bundle, everyone who visited has it.
sb_publishable_...) or legacy anon key in the browser is normal. A secret key (sb_secret_...) or legacy service_role key is not: it bypasses Row Level Security.3. Rotate first, clean history second
GitHub's own guidance: if the leaked data is a credential, revoke or rotate it first. Once it is rotated it is useless, and rewriting history may not even be needed. The order matters:
- Fix the cause. Move the call server-side so the new key will not leak the same way.
- Create the new key in the provider's dashboard.
- Deploy the new key everywhere (hosting env vars, Edge Functions, CI).
- Confirm nothing still uses the old key, then revoke it.
Supabase specifically
Supabase documents this exact procedure: create a new secret key in Settings > API Keys, replace the compromised key everywhere, confirm every component uses the new one, then retire the old one. Deleting a secret key cannot be undone. Legacy anon/service_role keys are deactivated in the same section instead, which is reversible. Supabase is deprecating the legacy keys by the end of 2026, so this is a good moment to move to sb_secret_ keys.
4. Optional: purge it from git history
If you still need the secret out of history, GitHub recommends git-filter-repo version 2.47 or later:
git-filter-repo --sensitive-data-removal --invert-paths --path PATH-TO-YOUR-FILE git push --force --mirror origin
This rewrites every commit hash, breaks old PR diffs, and forks or clones still contain the data. Read GitHub's page (linked below) before running it.
5. Keep .env away from your AI agent
Cursor
Cursor already ignores .env* and everything in .gitignore by default. To be explicit, add a .cursorignore in the project root (gitignore syntax):
.env .env.* **/credentials.json **/*.pem **/*.key
Cursor's docs add an important caveat: the Agent's terminal and MCP tools cannot be blocked by .cursorignore, and "complete protection isn't guaranteed." An agent that runs cat .env in the terminal still sees it. Review terminal commands before approving them.
Claude Code
Add deny rules to .claude/settings.json (shared with your team) or ~/.claude/settings.json (just you). This is the example from Anthropic's docs:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)"
]
}
}
Settings files are strict JSON, so no comments or trailing commas. Run /status inside Claude Code to confirm the file loaded. Deny rules take effect right away.
6. Stop the next leak
- Keep
.envand.env*.localin.gitignore. - Never put a secret behind
NEXT_PUBLIC_orVITE_. - Stage files by name (
git add file) instead ofgit add ., and checkgit diff --cachedbefore committing, as GitHub suggests. - Turn on GitHub push protection for the repo.
next step
Want a second pair of eyes?
Grab the free Lockdown Pack (security rules for Cursor and Claude Code plus a pre-launch checklist), or have us check the whole app for a fixed $99.
Sources
Every product step above was checked against these official pages. Last checked Oct 2026. Products change; if a menu moved, the docs below are the source of truth.