Skip to main content
友田 陽大

Free RLS policy generator

Generate correct Supabase RLS policies in seconds

Pick how your rows are owned and which operations to allow. Get ready-to-paste SQL that scopes every row to its caller — with the (select auth.uid()) performance idiom and WITH CHECK on writes, the way Supabase recommends. Then verify what you shipped with the checker.

Runs entirely in your browser — nothing is sent anywhere.

Ownership model
Operations to allow

Generated policies

alter table public.notes enable row level security;

create policy "notes_owner_select"
  on public.notes for select
  to authenticated
  using ((select auth.uid()) = user_id);

create policy "notes_owner_insert"
  on public.notes for insert
  to authenticated
  with check ((select auth.uid()) = user_id);

create policy "notes_owner_update"
  on public.notes for update
  to authenticated
  using ((select auth.uid()) = user_id)
  with check ((select auth.uid()) = user_id);

create policy "notes_owner_delete"
  on public.notes for delete
  to authenticated
  using ((select auth.uid()) = user_id);

These are correct templates for the common ownership shapes — they generate the right form, not a guarantee your authorization design is right. Confirm the columns and model fit your data, then verify with the checker. This complements design review; it does not replace it.

Why you can trust the output

Two sides of the same classifier

The generator (create) and the RLS checker (verify) reason about the same question: does a policy scope rows to the caller? Every shape here is run back through the checker's classifier in CI and can never come out over-permissive.

  1. 1

    Correct by construction

    Owner-bound predicates, WITH CHECK on every write, and the (select auth.uid()) wrapper — the exact shapes the field study found were missing in 9.2% of real apps.

  2. 2

    Proven, not asserted

    A test generates every model × operation and classifies it with the same engine as the checker, failing CI if any output is ever flagged as authenticated-only or anon-writable.

  3. 3

    Yours to review

    It generates the right form for your inputs. You confirm the columns and ownership model match your data — the tool can't know your business rules, and says so.

Generated it? Now verify the whole repo

Paste a policy into the checker to confirm it, or scan your entire project in one command. Need the access-control design reviewed end-to-end? I take that on as an audit.

npx @aegiskit/cli scan

No install, no signup — reads your repo locally and contacts nothing.

github.com/tomodahinata/aegis

FAQ

  • Are the generated policies safe to paste into production?

    They are the canonical owner-scoped shapes, and every one is verified by the same classifier as the RLS checker to never be over-permissive. But you must confirm the columns and ownership model match your data — the generator produces the correct form, not a guarantee your authorization design is right.

  • What does (select auth.uid()) do?

    It is Supabase's recommended performance idiom: wrapping the function in a subquery makes Postgres evaluate it once per query instead of once per row, which is dramatically faster on large tables. The plain auth.uid() = user_id is correct but slow. Toggle it off if you have a reason to.

  • Why does it add WITH CHECK on writes?

    USING controls which rows are visible; WITH CHECK controls which values may be written. Without it, a user can insert or update rows with someone else's owner id (a write bypass). The generator adds WITH CHECK to every INSERT/UPDATE automatically.

  • Does my table or column name get sent anywhere?

    No. The generator runs 100% in your browser and contacts nothing. It also sanitizes your input into safe SQL identifiers, so odd input can't produce broken or injectable SQL.

  • How is this different from the RLS checker?

    The generator creates correct policies; the checker verifies policies you already have. They are two sides of the same classifier — generate here, then paste your real migration into the checker to confirm nothing drifted.