SupabaseLow

Anonymous Key Misuse

Supabase anon key used without proper RLS policies in place, allowing unauthenticated data access.

Last updated 2026-01-15

What Is This Vulnerability

The Supabase anonymous (anon) key is a public API key designed to be used in client-side code. It is intentionally safe to expose only when Row Level Security (RLS) policies are correctly configured on every table. Anonymous key misuse occurs when developers rely on the anon key for API access but fail to implement adequate RLS policies, leaving tables accessible to anyone who possesses the key.

Unlike a secret key, the anon key carries the anon role in the JWT payload. If a table has RLS disabled or has overly permissive policies, any HTTP request bearing the anon key can read or modify data without authentication.

Why It's Dangerous

The anon key is embedded in every client bundle. Attackers can trivially extract it from browser DevTools, mobile binaries, or bundled JavaScript. When RLS is missing or misconfigured, this key becomes an all-access pass to your database.

Consequences include:

  • Full table reads — sensitive user data, billing records, and private content become publicly queryable.
  • Unauthorized writes — attackers can insert, update, or delete rows in unprotected tables.
  • Privilege escalation — if role-related tables lack RLS, attackers can elevate their own permissions.

Even a single unprotected table can compromise the entire application.

How to Detect

Query your database to find tables without RLS enabled:

SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public'
  AND rowsecurity = false;

You can also test from the client side using the anon key:

import { createClient } from '@supabase/supabase-js';

const supabase = createClient(SUPABASE_URL, ANON_KEY);

// Attempt to read a table that should be restricted
const { data, error } = await supabase.from('user_profiles').select('*');
if (data && data.length > 0) {
  console.warn('WARNING: user_profiles is accessible with anon key');
}

AuditYour.app automatically checks every public table for RLS status and tests whether the anon key can read or write data without authentication.

How to Fix

Enable RLS on every public table and create restrictive policies:

-- Step 1: Enable RLS
ALTER TABLE user_profiles ENABLE ROW LEVEL SECURITY;

-- Step 2: Create a policy that restricts reads to authenticated owners
CREATE POLICY "Users read own profile"
  ON user_profiles FOR SELECT
  USING (auth.uid() = id);

-- Step 3: Create a policy that restricts writes to authenticated owners
CREATE POLICY "Users update own profile"
  ON user_profiles FOR UPDATE
  USING (auth.uid() = id)
  WITH CHECK (auth.uid() = id);

-- Step 4: Deny anonymous access explicitly if needed
CREATE POLICY "Deny anon access"
  ON user_profiles FOR ALL
  USING (auth.role() != 'anon');

Audit all tables regularly. Use automated scanning to catch newly created tables that lack RLS before they reach production.

Scan your app for this vulnerability

AuditYourApp automatically detects security misconfigurations in Supabase and Firebase projects. Get actionable remediation in minutes.

Run Free Scan