The Canary Check #002: That SECURITY DEFINER function is a public API
Finding: privileged functions anyone can call
A SECURITY DEFINER function runs as its owner, which on Supabase usually bypasses RLS. Postgres grants EXECUTE to PUBLIC by default, and Supabase also grants it to anon and authenticated. So a helper you wrote for "admin only" can be called by anyone at /rest/v1/rpc/.... Supabase flags this as lints 0028 and 0029.
Our own review of 30 public Lovable and Bolt repos found 33% had at least one critical or high issue. Privileged functions were a recurring theme. It's a small sample, so treat it as directional.
Find them:
select p.proname, has_function_privilege('anon', p.oid, 'execute') as anon_can_call
from pg_proc p join pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public' and p.prosecdef;
Fix (pick one):
revoke execute on function public.my_fn(int) from anon, authenticated, public;
-- or, if it doesn't need elevated rights:
alter function public.my_fn(int) security invoker;
If it must stay definer, move it to a private schema and pin set search_path = ''.
Guide: https://prodcanary.com/guides/supabase-security-definer-function-risk/ Source: https://supabase.com/docs/guides/database/database-linter?lint=0028_anon_security_definer_function_executable
News
Lovable's Security view now runs a Quick scan on every publish and offers an on-demand Deep scan covering unauthenticated endpoints and leaked secrets. Lovable's docs say it doesn't replace a security review. (https://docs.lovable.dev/features/security)
Tip
Stop future functions from being auto-executable:
alter default privileges in schema public
revoke execute on functions from anon, authenticated, public;
Free scan: https://prodcanary.com/#scan