Supabase RLS Policy Checker for Vibe-Coded Apps: A Practical Guide
OverMCP Team
Quick answer
A Supabase RLS policy checker scans your database tables for missing or misconfigured row-level security policies, which are the most common security hole in vibe-coded apps. Without proper RLS, any authenticated (or sometimes unauthenticated) user can read, write, or delete data they shouldn't have access to. Use a dedicated scanner or manual queries to audit your policies before going live.
What to check first
Before diving into code, run through this checklist to spot obvious RLS issues in your Supabase project:
true or 1=1 as the USING expression. These allow all access regardless of user.auth.uid() or auth.role() to restrict data to the correct user.service_role key (which bypasses RLS), a scanner like our secret leak scanner can catch it.How to use a Supabase RLS policy checker
A Supabase RLS policy checker can be a database query, a CLI tool, or an automated scanner. Here's a step-by-step workflow you can run directly in your Supabase SQL editor.
Step 1: Query tables without RLS
Run this SQL to list all tables that have RLS disabled:
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname = 'public'
AND tablename NOT IN (SELECT tablename FROM pg_policies WHERE schemaname = 'public');This returns all public tables missing any policy. If you see tables here, you need to enable RLS and create policies.
Step 2: List all existing policies
Review every policy for potential gaps:
SELECT *
FROM pg_policies
WHERE schemaname = 'public';Pay attention to the using and with_check expressions. Look for:
USING (true) – allows anyoneUSING (auth.uid() IS NOT NULL) – allows any authenticated user (may be too broad)WITH CHECK – for INSERT/UPDATE, you need both USING (for existing rows) and WITH CHECK (for new/modified rows)Step 3: Test policies with a non-admin user
Create a test user or use the anon key to simulate a real request. In your app, call:
// Using supabase-js
const { data, error } = await supabase
.from('profiles')
.select('*')
.limit(1);
if (error) {
console.error('RLS blocked access:', error.message);
} else {
console.log('Data returned (RLS may be too permissive):', data);
}If you get data without being logged in, your RLS is broken.
Step 4: Automate the check with a scanner
Instead of running SQL manually every time, use a dedicated free AI app security scanner that checks Supabase RLS policies automatically. It connects to your project and reports missing or misconfigured policies in seconds.
Common mistakes in vibe-coded apps
AI coding tools like Cursor, Bolt.new, and Lovable often generate Supabase code that looks secure but has hidden RLS holes:
USING (true) for simplicity. AI models trained on these examples may replicate them.user_id can be null, the policy may return true for unauthenticated users..env file that gets leaked. Our continuous security monitoring can alert you if such keys appear in your repo.Step-by-step fix for common RLS gaps
Fix 1: Enable RLS on a table
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;Then create a policy:
CREATE POLICY "Users can view their own profile"
ON public.profiles
FOR SELECT
USING (auth.uid() = id);Fix 2: Add policies for all operations
Don't forget INSERT and UPDATE:
CREATE POLICY "Users can insert their own profile"
ON public.profiles
FOR INSERT
WITH CHECK (auth.uid() = id);
CREATE POLICY "Users can update their own profile"
ON public.profiles
FOR UPDATE
USING (auth.uid() = id)
WITH CHECK (auth.uid() = id);Fix 3: Restrict access to authenticated users only
If you need any authenticated user to read data (e.g., a public feed), use:
CREATE POLICY "Authenticated users can read posts"
ON public.posts
FOR SELECT
USING (auth.role() = 'authenticated');Avoid USING (true) unless the table is meant to be fully public (like a list of countries).
Fix 4: Use a helper function for complex checks
For multi-tenant apps, create a reusable function:
CREATE OR REPLACE FUNCTION public.is_org_member(org_id bigint)
RETURNS boolean
LANGUAGE sql STABLE
AS $$
SELECT EXISTS (
SELECT 1 FROM public.org_members
WHERE user_id = auth.uid() AND org_id = org_id
);
$$;Then use it in policies:
CREATE POLICY "Org members can view projects"
ON public.projects
FOR SELECT
USING (public.is_org_member(org_id));Common mistakes
service_role key gives full access. Use a Vercel security scanner to check environment variables.USING (true) "for now" and forget to tighten it before launch.FAQ
How do I run a Supabase RLS policy checker?
You can run SQL queries in the Supabase SQL editor to list tables without RLS and review existing policies. For automated scanning, use a dedicated free AI app security scanner that connects to your Supabase project and flags issues.
What does an RLS policy check look for?
It checks for tables with RLS disabled, policies using overly permissive expressions (like true), missing policies for certain operations (e.g., INSERT without WITH CHECK), and potential logic errors in the policy's USING clause.
Can I test RLS policies without deploying?
Yes. Use the Supabase dashboard's SQL editor to run test queries as different roles. You can also use the supabase-js client with an anon key to simulate real user requests in a local or staging environment.