Step-by-Step Guide
6 steps

How to Fix Supabase API Key Exposure

Supabase has two main keys: the anon key and the service_role key. The anon key is safe for frontend code but the service_role key must never be exposed. This guide helps you identify which key type is exposed and how to fix it.

Find security issues automatically before attackers do.

Follow These Steps

1

Identify which key type is exposed

Supabase keys are JWTs that start with eyJhbGci. Decode them to check the role field.

Code Example
// Decode your Supabase key to check its role
// Go to jwt.io and paste the key
// Look at the payload:
// { "role": "anon" }       -> Safe for frontend
// { "role": "service_role" } -> MUST be server-side only

// Or in code:
const payload = JSON.parse(atob(key.split('.')[1]))
console.log(payload.role) // "anon" or "service_role"
2

If anon key is exposed: enable RLS

The anon key is designed for frontend use but requires RLS to be secure. Without RLS, the anon key gives full database access.

Code Example
-- Enable RLS on every table
ALTER TABLE "your_table" ENABLE ROW LEVEL SECURITY;

-- Create policies
CREATE POLICY "Users read own data" ON "your_table"
  FOR SELECT TO authenticated
  USING ((select auth.uid()) = user_id);

The anon key itself is not the problem. Missing RLS policies are. Fix the policies, not the key.

3

If service_role key is exposed: rotate immediately

The service_role key bypasses all RLS. If exposed in frontend code, rotate it in the Supabase dashboard immediately.

Code Example
// Supabase Dashboard > Settings > API > Service Role Key
// Click "Generate new key"
// Update all server-side code with the new key

// CRITICAL: The service_role key must ONLY be used in:
// - Supabase Edge Functions
// - Backend servers
// - CI/CD pipelines
// NEVER in frontend/client code
4

Move service_role usage to Edge Functions

If you need elevated permissions for specific operations, use Edge Functions with the service_role key.

Code Example
// supabase/functions/admin-action/index.ts
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

const adminClient = createClient(
  Deno.env.get('SUPABASE_URL')!,
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! // Auto-injected by Supabase
)

// Use adminClient for operations that need to bypass RLS
const { data } = await adminClient.from('users').select('*')
5

Verify frontend only uses anon key

Search your frontend code to confirm only the anon key is used.

Code Example
// Search for Supabase client initialization
grep -rn "createClient" src/ --include="*.ts" --include="*.tsx"

// Verify the key being used
// Should use: NEXT_PUBLIC_SUPABASE_ANON_KEY
// Should NOT use: SUPABASE_SERVICE_ROLE_KEY
6

Scan and verify

Run a VAS scan to confirm RLS is enabled on all tables and no service_role key is exposed in frontend code.

What You'll Achieve

Your Supabase anon key is protected by RLS policies on every table. The service_role key is only used in server-side Edge Functions. No elevated-privilege keys are exposed in frontend code.

Common Mistakes to Avoid

Mistake

Trying to hide the anon key

Fix

The anon key is designed for frontend use. Security comes from RLS policies, not from hiding the key. Focus on writing proper RLS policies.

Mistake

Using service_role key in createBrowserClient

Fix

The browser client must always use the anon key. Move any service_role operations to Edge Functions or your backend.

Mistake

Enabling RLS without creating policies

Fix

RLS without policies blocks ALL access. Always create corresponding policies after enabling RLS.

Frequently Asked Questions

Is the Supabase anon key a secret?

No. The anon key is designed for client-side use. It only grants the permissions defined by your RLS policies. Without RLS, it gives full access. With proper RLS, it is safe.

How do I tell if my exposed key is anon or service_role?

Decode the JWT at jwt.io and check the role field in the payload. "anon" is safe for frontend. "service_role" must be server-side only.

Can I restrict what the anon key can do?

Yes, through RLS policies. Enable RLS on every table and write policies that define exactly what authenticated and anonymous users can access.

Ready to Secure Your App?

VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.

Start Security Scan