highCWE-862

RLS Enabled Without Policies

RLS is enabled on a table but no policies are defined, which silently blocks all access including legitimate queries from your application.

How It Works

When RLS is enabled on a Supabase table but no policies exist, PostgreSQL defaults to denying all access. This means your application cannot read, insert, update, or delete any rows through the client library. While this is secure by default, it often leads developers to bypass RLS entirely using the service_role key on the client side, which is far worse. The table appears broken, so devs either disable RLS or leak the service key — both critical security mistakes.

Vulnerable Code
-- RLS is on, but no policies exist
ALTER TABLE public.orders ENABLE ROW LEVEL SECURITY;
-- No policies created!

-- Developer "fixes" it by using service_role in the frontend:
const supabase = createClient(url, SERVICE_ROLE_KEY); // DANGER!
Secure Code
ALTER TABLE public.orders ENABLE ROW LEVEL SECURITY;

CREATE POLICY "users_read_own_orders" ON public.orders
  FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "users_insert_own_orders" ON public.orders
  FOR INSERT WITH CHECK (auth.uid() = user_id);
CREATE POLICY "users_update_own_orders" ON public.orders
  FOR UPDATE USING (auth.uid() = user_id);

Real-World Example

A common pattern in Supabase projects on GitHub: developers enable RLS to satisfy linting warnings, but never create policies. When their app breaks, they switch to the service_role key in client code, unknowingly giving every user full admin access to the database.

How to Prevent It

  • Always create at least one policy per operation when enabling RLS
  • Test RLS policies from the client immediately after writing migrations
  • Use Supabase CLI to verify policies: supabase db lint
  • Never use the service_role key in client-side code as a workaround

Affected Technologies

SupabaseNode.jsNext.jsReact

Data Hogo detects this vulnerability automatically.

Scan Your Repo Free

Related Vulnerabilities