Step-by-Step Guide
8 steps

How to Add Row Level Security to Your Lovable App

Lovable apps use Supabase as the database backend. Without Row Level Security, anyone with your Supabase URL can read and modify every row in your database. This is the single most critical vulnerability in Lovable apps. This guide walks you through enabling RLS and writing proper policies.

Find security issues automatically before attackers do.

Follow These Steps

1

List all tables in your database

Connect to your Supabase SQL editor and find all tables that need RLS.

Code Example
SELECT tablename, rowsecurity 
FROM pg_tables 
WHERE schemaname = 'public'
ORDER BY tablename;

Any table with rowsecurity = false is completely unprotected. These are your priority.

2

Enable RLS on every table

Run ALTER TABLE for each table. RLS must be explicitly enabled.

Code Example
-- Enable on all your tables
ALTER TABLE "profiles" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "posts" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "comments" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "likes" ENABLE ROW LEVEL SECURITY;
3

Create SELECT policies for user-owned data

Allow users to read only their own data. Use (select auth.uid()) for performance.

Code Example
CREATE POLICY "Users can view own profile" ON "profiles"
  FOR SELECT TO authenticated
  USING ((select auth.uid()) = user_id);

CREATE POLICY "Users can view own posts" ON "posts"
  FOR SELECT TO authenticated
  USING ((select auth.uid()) = author_id);
4

Create INSERT policies

Ensure users can only insert data with their own user_id.

Code Example
CREATE POLICY "Users can create own profile" ON "profiles"
  FOR INSERT TO authenticated
  WITH CHECK ((select auth.uid()) = user_id);

CREATE POLICY "Users can create posts" ON "posts"
  FOR INSERT TO authenticated
  WITH CHECK ((select auth.uid()) = author_id);
5

Create UPDATE and DELETE policies

Restrict updates and deletes to the row owner.

Code Example
CREATE POLICY "Users can update own profile" ON "profiles"
  FOR UPDATE TO authenticated
  USING ((select auth.uid()) = user_id);

CREATE POLICY "Users can delete own posts" ON "posts"
  FOR DELETE TO authenticated
  USING ((select auth.uid()) = author_id);
6

Handle shared/public data with read-only policies

For data that all users should see (like public posts), create broader SELECT policies while keeping write policies restrictive.

Code Example
-- Anyone authenticated can read public posts
CREATE POLICY "Authenticated users can view published posts" ON "posts"
  FOR SELECT TO authenticated
  USING (published = true);

-- But only authors can modify them
CREATE POLICY "Authors can update own posts" ON "posts"
  FOR UPDATE TO authenticated
  USING ((select auth.uid()) = author_id);
7

Test your policies

Use the Supabase SQL editor or API to verify policies work as expected.

Code Example
-- Test as a specific user (in SQL editor)
SET request.jwt.claim.sub = 'user-uuid-here';
SET request.jwt.claim.role = 'authenticated';

-- Try to read another user's data (should return empty)
SELECT * FROM profiles WHERE user_id != 'user-uuid-here';

Test both positive cases (user can access own data) and negative cases (user cannot access others data).

8

Scan to verify RLS is enforced

Run a VAS scan to confirm RLS is enabled on all tables and no bypass vulnerabilities exist.

What You'll Achieve

Every table in your Lovable app has RLS enabled with proper SELECT, INSERT, UPDATE, and DELETE policies. Users can only access their own data, and shared data has read-only access. Your database is protected against unauthorized access.

Common Mistakes to Avoid

Mistake

Enabling RLS but not creating any policies

Fix

RLS without policies blocks ALL access. Your app will break. Always create policies immediately after enabling RLS.

Mistake

Using USING (true) for all policies

Fix

This defeats the purpose of RLS. Always scope policies to auth.uid() matching the row owner for write operations.

Mistake

Forgetting to use (select auth.uid()) with the subquery wrapper

Fix

Use (select auth.uid()) instead of auth.uid(). The subquery evaluates once per query instead of once per row, significantly improving performance.

Mistake

Creating policies for service_role

Fix

The service_role bypasses RLS by default. Do not create service_role policies. Only create policies with TO authenticated.

Frequently Asked Questions

Will enabling RLS break my Lovable app?

If you enable RLS without creating policies, yes. The app will lose all data access. Always create policies immediately after enabling RLS. Plan your policies before running ALTER TABLE.

Do I need RLS if I use Supabase Auth?

Yes. Authentication verifies who the user is. RLS controls what they can access. Without RLS, any authenticated user can read all data from all other users.

How do I handle admin access with RLS?

Create a role or flag in your users table, then reference it in policies. Example: USING ((select auth.uid()) = user_id OR EXISTS (SELECT 1 FROM profiles WHERE id = (select auth.uid()) AND role = 'admin'))

Ready to Secure Your App?

VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.

Start Security Scan