What is the Supabase Anonymous Key?
Every Supabase project has two main API keys: the anon (anonymous) key and the service role key. The anon key is designed to be used in client-side code -- browsers, mobile apps, and other untrusted environments. It is a JWT that encodes the anon role in PostgreSQL.
// The anon key is a JWT with this payload:
{
"role": "anon",
"iss": "supabase",
"iat": ...,
"exp": ...
}
Is the Anon Key a Secret?
No. The anon key is intentionally designed to be public. It is embedded in your frontend JavaScript, compiled into mobile apps, and visible in browser network requests. Treating it as a secret is a misunderstanding of the Supabase security model.
However, this does NOT mean the anon key is harmless. It determines what the anon PostgreSQL role can do. If your RLS policies or role permissions are misconfigured, the anon key becomes a master key to your data.
The Real Risk
The anon key grants access to everything the anon PostgreSQL role is allowed to do. By default, Supabase grants the anon role:
- Access to the PostgREST API (all tables with RLS disabled or permissive policies)
- Access to the Storage API (all buckets with RLS disabled or permissive policies)
- Access to Edge Functions (unless they verify the JWT role)
- Access to Realtime subscriptions
Scenario: RLS Disabled
# With just the anon key, an attacker can read all data:
curl 'https://your-project.supabase.co/rest/v1/users?select=*' \
-H "apikey: YOUR_ANON_KEY" \
-H "Authorization: Bearer YOUR_ANON_KEY"
If users table has RLS disabled, this returns every row. The attacker does not need to be authenticated.
Scenario: Overly Permissive RLS
-- This policy allows the anon role to read everything
CREATE POLICY "Public read" ON users
FOR SELECT USING (true);
Even with RLS enabled, a policy that evaluates to true for all rows is equivalent to having RLS disabled.
Securing the Anon Role
1. Enable RLS on Every Table
This is the most critical step. No exceptions:
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE payments ENABLE ROW LEVEL SECURITY;
-- Do this for EVERY table
2. Revoke Default Permissions
By default, new tables may grant SELECT to the anon role. You can revoke this:
-- Revoke all direct privileges on the table
REVOKE ALL ON users FROM anon;
-- Grant only through RLS policies
GRANT SELECT ON users TO anon;
-- Now RLS policies control what the anon role can see
3. Restrict the Anon Role to Authenticated Actions
For most applications, the anon role should have very limited access. Most data access should require authentication (authenticated role):
-- Only allow authenticated users to read, not anon
CREATE POLICY "Authenticated read own data"
ON users FOR SELECT
USING (auth.uid() = id);
-- This policy implicitly excludes the anon role because
-- auth.uid() returns null for unauthenticated requests
4. Audit Function Permissions
Check which functions the anon role can execute:
SELECT routine_name, routine_schema
FROM information_schema.routine_privileges
WHERE grantee = 'anon' AND privilege_type = 'EXECUTE';
Revoke access to any functions that should not be publicly callable:
REVOKE EXECUTE ON FUNCTION sensitive_function FROM anon;
The Service Role Key
Unlike the anon key, the service role key bypasses RLS entirely. It must NEVER be exposed in client-side code:
// NEVER do this in a browser or mobile app
const supabase = createClient(url, SERVICE_ROLE_KEY); // CRITICAL VULNERABILITY
// The service role key should only exist in:
// - Edge Functions (as environment variables)
// - Server-side code
// - CI/CD pipelines
If the service role key is leaked (e.g., hardcoded in an APK), an attacker has full unrestricted access to your database, storage, and auth system.
Monitoring Anon Key Usage
Monitor your Supabase logs for suspicious activity from the anon role:
- Unexpected table access patterns
- High-volume requests from single IPs
- Requests to tables that should only be accessed by authenticated users
Automated Detection
AuditYour.app tests your project by making requests with just the anon key to every exposed table and endpoint. This reveals exactly what an attacker with your (public) anon key can access, and provides specific remediation steps for each finding.
Scan your app for this vulnerability
AuditYourApp automatically detects security misconfigurations in Supabase and Firebase projects. Get actionable remediation in minutes.
Run Free ScanRelated
guides
Complete Guide to Supabase Row Level Security
Deep dive into RLS policies, patterns, and common pitfalls
guides
Hardening Supabase Edge Functions
Best practices for secure Edge Function development
guides
Supabase Database Security Best Practices
Comprehensive Postgres/Supabase DB hardening guide
guides
Securing Supabase Storage Buckets
How to properly configure and secure storage buckets