Supabase Security Advisor warnings explained

Security Advisor lists security definer views, search_path, or RLS? Here is what the common lints mean and the fix Supabase prints for each.

Reviewed October 17, 2026

What it means in plain English

Security Advisor is a list of checks Supabase ships with the project. Open it in Studio, or run supabase db advisors from the CLI. Supabase says some findings may be intentional, so compare each one with the access you actually want before you change the database.

The names below are the security lints that show up on apps built by Lovable, Bolt, and Cursor. Levels and summaries are the ones on the Advisors page.

Likely causes

  • Lint 0013_rls_disabled_in_public is level ERROR, "Table publicly accessible." Anyone with the project URL can read, edit, and delete rows in that table. See how to check that RLS is on.
  • Lint 0008_rls_enabled_no_policy is level INFO, "No access rules defined." RLS is on and there is no policy, so the API cannot read or write. That is safer than 0013. The empty list is Supabase returns an empty array. A refused write is new row violates row-level security policy.
  • Lint 0010_security_definer_view is a view in public that runs as its owner. Postgres creates views as SECURITY DEFINER by default, so the view uses the owner's privileges and ignores RLS. Supabase says a view created that way in the public schema can expose more through the API than you meant.
  • Lint 0011_function_search_path_mutable is a function with no fixed search_path. Supabase says an unqualified name can resolve to a different object depending on who runs the function.
  • Lint 0015_rls_references_user_metadata is level ERROR, "Security policy relies on user-editable data." user_metadata is data the user can change. A policy that trusts it can be bypassed.

How to fix it, step by step

  1. For 0013, enable RLS, then add a policy for each operation the app needs. Supabase's example:
alter table public.blog enable row level security;
  1. For 0008, add the policy the app needs. Do not drop RLS to clear the info finding.
  2. For 0010, recreate the view so it runs as the caller. Supabase's example:
create view public.order_items
  with (security_invoker = on)
  as
  select id
  from app.order_items;

Replace the select list and the source table with your own. security_invoker = on is SECURITY INVOKER: the view uses the permissions of the user running the query, so RLS on the underlying table applies.

  1. For 0011, set an empty search path and schema-qualify every name inside the function. Supabase's example:
create or replace function example_function()
  returns void
  language sql
  set search_path = ''
  as $$
    -- Your SQL code here. Write public.your_table, not your_table.
  $$;
  1. For 0015, remove user_metadata from the policy. Supabase says the user can change it, so it is not a place to store who may access a row. The RLS guide says raw_app_meta_data cannot be updated by the user. A column such as user_id checked with auth.uid() is the usual replacement.
  2. Paste this to the AI tool:
Read the Supabase Security Advisor findings. For 0013_rls_disabled_in_public, enable RLS and add policies. For 0008_rls_enabled_no_policy, add a policy and do not disable RLS. For 0010_security_definer_view, recreate the view with (security_invoker = on). For 0011_function_search_path_mutable, set search_path = '' and schema-qualify every reference. For 0015_rls_references_user_metadata, stop using user_metadata in policies. Do not drop policies to silence a warning.

How to check it worked

  • Reload Security Advisor. The lint you fixed is gone, or you have written down why you are keeping it.
  • A request with only the publishable key cannot read a table you did not write a public policy for.
  • The app still loads the rows a signed-in user is supposed to see.

Sources

More Supabase RLS and permissions fixes

Keep going on your own.

The guides stay free. A deep leak report is $15. Fix packs are $24, or $49 for all three. There is no done-for-you repair.

See products