Row level security

    What is row level security?

    SHORT ANSWER

    Row level security (RLS) is a database setting that decides which rows each user is allowed to see or change. With it switched on, a logged-in user only gets their own data. With it off, anyone who has your app's public key can read or edit every row in the table.

    Also called: RLS

    ON THIS PAGE

    What it means

    Your database is made of tables, and each table is made of rows. One row might be one user's profile, one order, or one message. Row level security is a switch, plus a set of rules called policies, that decides which of those rows a person can see or change.

    Without it, your database has no idea who is asking. If someone has the key your app uses to talk to the database (and in most AI-built apps that key is public by design), they can ask for everything.

    Why it matters for vibe-coded apps

    Tools like Lovable and Bolt often use Supabase as the database. Supabase expects you to turn on row level security for every table, but the AI doesn't always do it, especially for tables added later in a project.

    IF THIS IS WRONG IN YOUR APP
    • Your users' names, emails and messages can be downloaded by anyone.
    • Someone could change or delete other people's data.
    • Your app works perfectly while this is happening, so you won't notice.

    Example

    Say your app has a profiles table. The AI created it, but never turned on row level security.

    ✕ RISKYAnyone with the public key can read every profile
    -- Table created, but RLS never switched on
    create table profiles (
      id uuid primary key,
      email text,
      phone text
    );
    ✓ SAFEREach user can only read their own profile
    alter table profiles enable row level security;
    
    create policy "Users can read their own profile"
    on profiles for select
    using ( auth.uid() = id );

    The policy says: only return a row if the logged-in user's ID matches the row's ID.

    How to check if your app has this problem

    1. 1Open your Supabase dashboard and go to Table Editor.
    2. 2Look for any table marked "RLS disabled" or "Unrestricted".
    3. 3For tables with RLS on, open Authentication → Policies and make sure each one has at least one policy.

    The quicker way: LetMeCheck tests for this automatically, from the outside, the way an attacker would.

    Run a free scan →

    How to fix it

    1. 1Turn on row level security for every table that holds user data.
    2. 2Add a policy for each action (read, add, change, delete) that limits it to the row's owner.
    3. 3Test it: log in as one user and make sure you can't see another user's data.
    4. 4Run a check again to confirm the table is no longer open.
    FIX PROMPT · PASTE INTO YOUR AI TOOL

    Turn on row level security for every table in my Supabase database. For each table with a user_id column, add policies so a logged-in user can only read, insert, update and delete their own rows. Don't change any other logic.

    Check if your app has this problem

    Paste your website and we'll check for row level security issues and other common issues in AI-built apps. Free, about a minute, and nothing on your site is changed.

    Last updated