Lovable connects to Supabase using the anon key, and that key lives in every user's browser. Without Row Level Security, any signed-in user can run SELECT * FROM your_table and get every row, not just their own. CheckYourVibe sees this as the most common finding in Lovable+Supabase apps. Over half of scanned Lovable projects have at least one table with RLS disabled.
Fixing it takes about 10 minutes of SQL.
TL;DR
Enable RLS on every Supabase table your Lovable app uses, then add a USING (auth.uid() = user_id) policy for each one. Without policies, enabling RLS blocks all access. Add the policy first. Run the audit query below to find every table that's currently unprotected.
Step 1: Audit Which Tables Have RLS Disabled
Open Supabase Dashboard, go to SQL Editor, and run:
SELECT
schemaname,
tablename,
rowsecurity
FROM pg_tables
WHERE schemaname = 'public'
AND rowsecurity = false
ORDER BY tablename;
Every table in the results is wide open. Write down the list. You'll enable RLS on each one in the next step.
Enabling RLS on a table with no policies blocks all reads and writes immediately. Don't enable RLS until you have the policy ready. Do both in the same SQL transaction.
Step 2: Enable RLS and Add a Read Policy Together
For a table called profiles where each row belongs to a user:
-- Enable RLS
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
-- Allow users to read only their own row
CREATE POLICY "Users can read own profile"
ON profiles
FOR SELECT
USING (auth.uid() = user_id);
auth.uid() returns the UUID of the currently authenticated user. The USING clause filters which rows they can see. If user_id is the column that stores the owner, this one policy protects the table for reads.
Repeat this pattern for every table in your audit list.
Step 3: Add Write Policies
Read-only is a start, but users also need to insert, update, and delete their own data:
-- Allow users to insert rows for themselves
CREATE POLICY "Users can insert own data"
ON profiles
FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- Allow users to update only their own rows
CREATE POLICY "Users can update own data"
ON profiles
FOR UPDATE
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- Allow users to delete only their own rows
CREATE POLICY "Users can delete own data"
ON profiles
FOR DELETE
USING (auth.uid() = user_id);
INSERT and UPDATE use WITH CHECK (what they're allowed to write) in addition to USING (what they're allowed to touch).
Step 4: Handle Tables Without a user_id Column
Some Lovable apps have reference tables (categories, lookup lists, config rows) that should be readable by anyone but writable only by admins. For those:
ALTER TABLE categories ENABLE ROW LEVEL SECURITY;
-- Anyone (including unauthenticated) can read
CREATE POLICY "Public read access"
ON categories
FOR SELECT
USING (true);
USING (true) means the policy always passes. You're not restricting reads, but RLS is still on, so any missing write policy will block unintended inserts.
If your Lovable app has a multi-user or team model, your policies get more complex. The supabase-rls-policies post has examples for teams, admins, and shared data.
Step 5: Verify RLS Is Active
Two ways to check:
In Supabase Dashboard: Go to Table Editor, click a table, and look for the green "RLS enabled" badge at the top.
With the audit query: Re-run the Step 1 query. Every table that had rowsecurity = false should now return true.
With CheckYourVibe: Run a scan on your app URL. The scanner checks for Supabase RLS coverage and flags any unprotected tables as a critical finding.
Re-test your Lovable app end-to-end. Log in as two different test users and confirm that User A cannot read User B's data. If something breaks, you likely have a missing policy. Check the Supabase Logs tab under API for the specific query that failed.
Common Mistakes
Missing user_id column. If Lovable didn't generate a user_id column on a table, you can't use auth.uid() = user_id. Add the column first: ALTER TABLE your_table ADD COLUMN user_id uuid REFERENCES auth.users(id); then backfill it.
Forgetting the storage bucket. Supabase Storage has its own RLS system separate from tables. If your Lovable app uploads files, check Storage Policies too.
Using service_role in the client. If your Lovable app has the service_role key in the frontend (starts with eyJhbGci and decodes to "role": "service_role"), RLS won't protect you at all. Service role bypasses RLS by design. Move it to a server-side function immediately.
Does Lovable enable RLS automatically?
No. Lovable generates the Supabase schema but leaves RLS off by default. You enable it manually in the Supabase SQL Editor on each table.
What happens if I skip RLS in my Lovable app?
Any signed-in user can query any row in your database directly using the anon key that's visible in their browser. They don't need to find a bug in your code, they just call the Supabase REST API directly.
Can I use auth.uid() in RLS policies with Lovable?
Yes. Lovable uses Supabase Auth, so auth.uid() returns the current user's UUID for every authenticated request. Your policy just needs USING (auth.uid() = user_id) where user_id is the ownership column.
My app broke after enabling RLS. What happened?
You enabled RLS before creating any policies. RLS with zero policies blocks all access. Add the SELECT policy first, confirm reads work, then add INSERT/UPDATE/DELETE policies one at a time.
How do I test that RLS is actually working?
Log in as two different users and confirm neither can read the other's data. You can also run a CheckYourVibe scan or use the Supabase API Explorer with the anon role to query a protected table directly.
Scan your Lovable app now to find every table with RLS disabled and other Supabase misconfigurations.