Home / The Canary Check

The Canary Check #002: That SECURITY DEFINER function is a public API

One finding, one fix, before you ship.

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

Get the next one

A 3-minute security note for people shipping with Lovable, Bolt, Cursor, Supabase and Firebase, on weekday mornings.

Subscribe free