Vulnerability
Supabase

IDOR in Supabase Applications

Supabase's Row Level Security (RLS) is the primary defense against IDOR. However, IDOR vulnerabilities appear when RLS policies are missing, when they check authentication but not ownership, and when client-side filtering gives a false sense of security.

Scan Your Supabase App

How IDOR Manifests in Supabase

IDOR in Supabase apps occurs when: RLS policies check auth.uid() IS NOT NULL (authenticated) but not auth.uid() = user_id (ownership). Any logged-in user can access any record. The frontend filters data with .eq("user_id", userId) but the RLS policy allows broader access. An attacker bypasses the client filter by querying Supabase directly. Storage policies allow any authenticated user to access files by changing the path. RPC functions do not check ownership of the records they operate on.

Real-World Impact

A Supabase app for medical records had an RLS policy that allowed SELECT for any authenticated user. The frontend filtered by the current user's ID, so it appeared secure. An attacker queried the Supabase REST API directly, bypassing the frontend filter, and downloaded all patient medical records.

Step-by-Step Fix

1

Write ownership-based RLS policies

Ensure every RLS policy checks that the user owns the record.

-- UNSAFE: any authenticated user can read all records
CREATE POLICY "Authenticated users can read" ON "documents"
  FOR SELECT TO authenticated
  USING (true);

-- SAFE: users can only read their own records
CREATE POLICY "Users can read own documents" ON "documents"
  FOR SELECT TO authenticated
  USING ((select auth.uid()) = user_id);

-- For shared resources, check membership
CREATE POLICY "Team members can read" ON "documents"
  FOR SELECT TO authenticated
  USING (
    EXISTS (
      SELECT 1 FROM team_members
      WHERE team_members.team_id = documents.team_id
      AND team_members.user_id = (select auth.uid())
    )
  );
2

Secure Supabase Storage

Apply RLS-style policies to storage buckets.

-- Storage policies for user uploads
CREATE POLICY "Users can upload own files" ON storage.objects
  FOR INSERT TO authenticated
  WITH CHECK (
    bucket_id = 'user-files'
    AND (storage.foldername(name))[1] = (select auth.uid())::text
  );

CREATE POLICY "Users can view own files" ON storage.objects
  FOR SELECT TO authenticated
  USING (
    bucket_id = 'user-files'
    AND (storage.foldername(name))[1] = (select auth.uid())::text
  );
3

Test RLS policies thoroughly

Test by querying as different users to verify isolation.

// Test script: verify User B cannot access User A's data
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);

// Sign in as User B
await supabase.auth.signInWithPassword({
  email: 'userB@test.com',
  password: 'test-password',
});

// Try to read User A's document by ID
const { data, error } = await supabase
  .from('documents')
  .select()
  .eq('id', 'user-a-document-id');

// Should return empty array if RLS is correct
console.log('Data:', data); // Should be []
console.log('Error:', error); // Should be null (not an error, just no results)

Prevention Best Practices

1. Always include (select auth.uid()) = user_id in RLS policies. 2. Never rely on client-side filtering for security. 3. Test RLS policies by querying as a different user. 4. Use RLS on Supabase Storage for file access control. 5. Check ownership in RPC functions.

How to Test

1. Create two test accounts and data for each. 2. Query the Supabase REST API directly (bypass frontend) as User B for User A's data. 3. Check RLS policies: SELECT * FROM pg_policies; 4. Test storage access by trying to download another user's files. 5. Use Vibe App Scanner to detect IDOR in your Supabase application.

Frequently Asked Questions

Does RLS prevent all IDOR in Supabase?

RLS prevents IDOR at the database level when policies check ownership (auth.uid() = user_id). However, RPC functions that bypass RLS (SECURITY DEFINER), Edge Functions, and Storage need separate authorization checks.

Is client-side filtering enough for IDOR prevention?

No. Client-side filtering only affects what the UI displays. An attacker can query the Supabase REST API directly, bypassing your frontend. RLS is the only reliable server-side enforcement for Supabase queries.

How do I handle shared resources in Supabase?

Create a junction table (e.g., team_members) and write RLS policies that check membership. Use EXISTS subqueries in policies to verify the user belongs to the team/org that owns the resource.

Is Your Supabase App Vulnerable to IDOR?

VAS automatically scans for idor vulnerabilities in Supabase applications and provides step-by-step remediation guidance with code examples.

Scans from $5, results in minutes. Get actionable fixes tailored to your Supabase stack.