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_publicis 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_policyis 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_viewis a view inpublicthat runs as its owner. Postgres creates views asSECURITY DEFINERby default, so the view uses the owner's privileges and ignores RLS. Supabase says a view created that way in thepublicschema can expose more through the API than you meant. - Lint
0011_function_search_path_mutableis a function with no fixedsearch_path. Supabase says an unqualified name can resolve to a different object depending on who runs the function. - Lint
0015_rls_references_user_metadatais level ERROR, "Security policy relies on user-editable data."user_metadatais data the user can change. A policy that trusts it can be bypassed.
How to fix it, step by step
- 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;
- For 0008, add the policy the app needs. Do not drop RLS to clear the info finding.
- 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.
- 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.
$$;
- For 0015, remove
user_metadatafrom 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 saysraw_app_meta_datacannot be updated by the user. A column such asuser_idchecked withauth.uid()is the usual replacement. - 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
Related fixes
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.