critical
Security Vulnerability

Row Level Security (RLS) Misconfiguration

RLS misconfiguration occurs when database tables lack proper row-level access controls, allowing unauthorized users to read, modify, or delete any data.

Scan for This Vulnerability

What is Row Level Security (RLS) Misconfiguration?

Row Level Security (RLS) is a PostgreSQL feature used by Supabase to control which rows users can access. When RLS is disabled or misconfigured, your entire database becomes accessible to anyone with your public anon key - which is visible in your frontend code by design.

How It Happens

  • RLS not enabled on tables (tables are open by default)
  • Overly permissive policies (e.g., 'allow all')
  • Missing policies for certain operations (SELECT, INSERT, UPDATE, DELETE)
  • Policies that don't properly check auth.uid()
  • AI code generators skipping security configuration

Impact

Complete data breach - attackers can read all user data

Data manipulation - attackers can modify or delete records

Privacy violations and regulatory non-compliance

Reputational damage and loss of user trust

Potential legal liability

How to Detect

  • Query your database with just the anon key (no authentication)
  • Check if you can read data from tables you shouldn't access
  • Use VAS to automatically test RLS configuration
  • Run: SELECT * FROM your_table; as an anonymous user

How to Fix

Enable RLS on all tables

First, enable Row Level Security on every table that contains data.

-- Enable RLS
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;

Create restrictive policies

Write policies that check authentication and restrict access to user's own data.

-- Users can only read their own profile
CREATE POLICY "Users read own profile" ON profiles
  FOR SELECT TO authenticated
  USING ((select auth.uid()) = id);

-- Users can only update their own profile
CREATE POLICY "Users update own profile" ON profiles
  FOR UPDATE TO authenticated
  USING ((select auth.uid()) = id);

Test your policies

Verify policies work by querying as different user contexts.

-- As anonymous user, this should return nothing:
SELECT * FROM profiles;

-- As authenticated user, should only return own data:
SELECT * FROM profiles WHERE id = auth.uid();

Is Your App Vulnerable?

VAS automatically scans for row level security (rls) misconfiguration and provides detailed remediation guidance.

Run Security Scan