← All posts
supabasesecurityvibe-codingsecret-leakfix

How to Fix a Leaked Supabase Anon Key in a Vibe-Coded App

O

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:

  • [ ] Check for service_role key leaks — This key has admin privileges. Search your codebase for service_role or supabase_service_role. If it's exposed, rotate it immediately.
  • [ ] Audit your RLS policies — Go to Supabase Dashboard > SQL Editor and run: SELECT * FROM pg_policies; Ensure every table has RLS enabled and policies restrict access to authenticated users.
  • [ ] Check environment variables — Make sure keys are stored in .env.local (not .env) and never committed to Git. Use git log -p to check if keys were ever committed.
  • [ ] Scan GitHub for leaks — Use a secret leak scanner to find exposed keys in your repository.
  • [ ] Review your app's client-side code — The anon key is visible in browser DevTools. That's fine. But ensure no secret logic relies on the anon key being secret.
  • 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)

  • Go to Supabase Dashboard > Project Settings > API.
  • Click "Rotate" next to the anon public key. This invalidates the old key.
  • If the service_role key leaked, rotate that too.
  • Update your .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 --all

    Warning: 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.*.local

    Common 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

  • Use environment variables from day one. In Next.js, use NEXT_PUBLIC_SUPABASE_ANON_KEY for the anon key (public) and SUPABASE_SERVICE_ROLE_KEY for the service role (server-only).
  • Set up pre-commit hooks to prevent committing secrets. Use tools like secretlint or a continuous security monitoring service.
  • Review AI-generated code for security issues. AI tools often miss RLS policies or hardcode keys.
  • Use a [Vercel security scanner](https://www.overmcp.com/connect/vercel) to automatically check your deployments for leaks.
  • 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.

    Is your app secure?

    Free scan in 30 seconds. No signup needed.

    Scan My App Free