Question

Let people who are not logged in submit a contact form into Supabase, safely?

Open · 184 viewsasked by valentina_s

Landing page with a waitlist form. No accounts. I want the form to insert into a waitlist table. Right now it fails with the RLS error. What's the right policy? I don't want strangers reading the list of emails.

What I’ve tried

Tried create policy ... for all using (true) which works but then I can also select everything with the anon key, which is exactly what I don't want.

Comment
Do you ever need to read the list from the app, or only from the dashboard? sanne_dev
only dashboard valentina_s

3 answers

sanne_dev

Insert-only policy for the anon role, no select policy at all:

create policy "anyone can join waitlist" on public.waitlist
  for insert to anon
  with check (true);

With RLS on and no select policy, reads return an empty array. One gotcha: don't chain .select() after the insert in your client code, because returning the row needs select permission and you'll get the RLS error again.

Comment
the .select() thing was exactly why my first attempt failed. ok! valentina_s
chidi_eze

Sanne's policy is right. The part people skip: with the anon key public, anyone can script 50,000 inserts into that table. Add a check constraint on the email length and format, and consider sending the form through a server action or edge function with a captcha (Turnstile is free) instead of inserting directly from the browser.

Comment
Turnstile looks easy enough. Is the check done in an edge function then? valentina_s
Yes, verify the token server side (edge function or server action), then insert. Never trust a captcha checked only in the browser. chidi_eze
sam_builds

I did the server action route for my waitlist, using the anon key server side with the same insert policy. Keeps the table out of the browser entirely and you can rate limit per IP there.

Comment