How to Fix a Leaked Supabase Anon Key in a Vibe-Coded App
OverMCP Team
Quick answer
If you've leaked your Supabase anon key in a vibe-coded app, it's not a security emergency by itself — the anon key is meant to be public. But if you also exposed your service_role key or have permissive Row Level Security (RLS) policies, you need to rotate the keys immediately and fix your RLS rules. The fix involves: 1) checking what else leaked, 2) tightening RLS policies, and 3) rotating the anon key in Supabase dashboard.
What to check first
Before you panic, understand that the Supabase anon key is designed to be public — it's used by your frontend to interact with the database. The real danger is if your vibe-coded app also leaked the service_role key or has weak RLS policies. Here's your checklist:
service_role or supabase_service_role. If it's exposed, rotate it immediately.SELECT * FROM pg_policies; Ensure every table has RLS enabled and policies restrict access to authenticated users..env.local (not .env) and never committed to Git. Use git log -p to check if keys were ever committed.Step-by-step fix
1. Identify what leaked
If you committed a .env file with both keys, you need to act. Run this in your terminal to search for leaked keys:
grep -r "supabase_key" . --include="*.{js,ts,jsx,tsx,env,json,yml}"
grep -r "service_role" . --include="*.{js,ts,jsx,tsx,env,json,yml}"2. Rotate the anon key (and service_role key if leaked)
anon public key. This invalidates the old key..env.local with the new keys.3. Fix RLS policies (the real fix)
Vibe-coded apps often generate tables with RLS disabled or with permissive policies. Here's how to fix a common pattern:
-- Enable RLS on a table
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
-- Create a policy for authenticated users to read their own data
CREATE POLICY "Users can view own profile" ON profiles
FOR SELECT
USING (auth.uid() = id);
-- Create a policy for authenticated users to update their own data
CREATE POLICY "Users can update own profile" ON profiles
FOR UPDATE
USING (auth.uid() = id);4. Remove leaked keys from Git history
If you committed the file containing keys:
# Remove the file from Git history (if it was .env)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# Force push to overwrite remote history
git push origin --force --allWarning: This rewrites history. Coordinate with your team.
5. Add a .gitignore entry
Ensure .env and .env.local are in your .gitignore:
# .gitignore
.env
.env.local
.env.*.localCommon mistakes
Mistake 1: Thinking the anon key is a secret
The anon key is public. It's meant to be in your frontend code. The danger is when your app trusts the anon key to protect data — it should rely on RLS policies instead.
Mistake 2: Disabling RLS entirely
AI coding tools sometimes generate SQL migration files with ALTER TABLE ... DISABLE ROW LEVEL SECURITY; for simplicity. This makes your database accessible to anyone with the anon key. Always enable RLS.
Mistake 3: Storing keys in `.env` and committing it
Vibe-coded projects often start with a single .env file that gets committed. Use .env.local for local secrets and add it to .gitignore. For production, use environment variables in your deployment platform (Vercel, Netlify, etc.).
Mistake 4: Not scanning for leaks after a fix
After rotating keys, run a free AI app security scanner to confirm no other secrets are exposed.
How to prevent future leaks
NEXT_PUBLIC_SUPABASE_ANON_KEY for the anon key (public) and SUPABASE_SERVICE_ROLE_KEY for the service role (server-only).secretlint or a continuous security monitoring service.FAQ
If the anon key is public, why rotate it?
Rotating the anon key is a precaution if you suspect it was used in an insecure context (e.g., exposed in a public GitHub repo without RLS). But the real fix is always RLS policies.
Can someone access my database with just the anon key?
Only if RLS is disabled or misconfigured. The anon key without proper RLS is like a key to an unlocked door — the key doesn't matter if the door is open.
How do I check if my RLS policies are secure?
Run SELECT * FROM pg_policies; in Supabase SQL Editor. Look for policies that use USING (true) or allow public access. Ensure every table has policies that restrict to auth.uid() or similar.