RPC Functions Without Authentication
Supabase database functions (RPC) callable from the client without checking auth.uid(), allowing anonymous users to execute privileged operations.
How It Works
Supabase exposes PostgreSQL functions via the RPC endpoint, making them callable from the client library. If a function does not verify auth.uid() or check the user's role, any anonymous user can invoke it. This is especially dangerous for functions that modify data, perform admin operations, or return sensitive information. Unlike tables with RLS, functions execute with the privileges of the function owner (typically the postgres superuser), bypassing all RLS policies.
CREATE OR REPLACE FUNCTION delete_user_data(target_user_id uuid)
RETURNS void AS $$
BEGIN
DELETE FROM public.profiles WHERE id = target_user_id;
DELETE FROM public.documents WHERE user_id = target_user_id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;CREATE OR REPLACE FUNCTION delete_user_data()
RETURNS void AS $$
BEGIN
IF auth.uid() IS NULL THEN
RAISE EXCEPTION 'Not authenticated';
END IF;
DELETE FROM public.profiles WHERE id = auth.uid();
DELETE FROM public.documents WHERE user_id = auth.uid();
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;Real-World Example
In 2024, a task management app built on Supabase had an RPC function that granted admin roles. The function accepted a user_id parameter without checking auth.uid(), allowing any anonymous user to promote themselves to admin and access all workspace data.
How to Prevent It
- Always check auth.uid() IS NOT NULL at the start of every RPC function
- Use auth.uid() instead of accepting user IDs as parameters
- Prefer SECURITY INVOKER over SECURITY DEFINER when possible
- Revoke EXECUTE on functions from the anon and authenticated roles if not needed
Affected Technologies
Data Hogo detects this vulnerability automatically.
Scan Your Repo FreeRelated Vulnerabilities
Row Level Security Disabled
criticalSupabase tables without RLS enabled allow any authenticated or anonymous user to read, insert, update, and delete all rows using the client library.
RLS Policy with USING(true)
criticalRLS policies that use USING(true) or WITH CHECK(true) effectively disable row-level security by allowing all operations for all users.
RLS Enabled Without Policies
highRLS is enabled on a table but no policies are defined, which silently blocks all access including legitimate queries from your application.
Service Role Key Exposed
criticalThe Supabase service_role key is hardcoded in frontend code, committed to a repository, or exposed in client bundles, granting full database admin access to anyone.