dreamlabs.pro/services/supabase-rls-checklist · Updated Oct 7, 2026

[Free checklist]

Supabase Row Level Security (RLS) Checklist

Supabase gives your frontend a direct line to Postgres, which is a big part of why teams building in Lovable, in their own repositories with AI coding tools, or by hand get to a working product in days. The key that makes it possible sits in every visitor's browser by design, so Row Level Security is what decides who sees which row. When your policies say exactly that, you can open sign-ups, answer a security questionnaire with evidence, and keep shipping without wondering what a stranger with your key can do. This checklist covers 23 checks across RLS, grants, keys, functions, Storage and Realtime, including the Lovable-era exposure pattern behind CVE-2025-48757. Each one says what to look for, why it matters, how to test it with SQL, curl or the Dashboard, and which Supabase documentation backs it. Run the tests only against projects you own, ideally a staging branch.

Updated · 23 checks · 7 sections

[01]

Start here: what can a stranger reach?

Your project URL and publishable (or legacy anon) key sit in every visitor's browser by design. Supabase's own analogy: the publishable key is taped to the front door, and it only opens the lobby. These four checks confirm the lobby is all it opens.

  • Why it matters and how to test it

    Why it matters

    Supabase's guide opens with it: a table in an exposed schema without RLS is readable and writable by any role with a grant on it. Tables created in the Dashboard get RLS by default, but tables created in the SQL Editor, by a migration or by an AI coding tool need it switched on explicitly.

    How to test

    Run the query below in the SQL Editor. Any row showing rowsecurity = false is a finding. Fix it in a migration with alter table public.<table> enable row level security;, then write policies, because once RLS is on the table returns nothing to the public key until a policy allows it.

    select schemaname, tablename, rowsecurity
    from pg_tables
    where schemaname = 'public'
    order by rowsecurity, tablename;

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    Postgres checks grants before it looks at policies. On projects created under the old defaults, every new public table got select, insert, update and delete for anon, authenticated and service_role, and adding policies doesn't take those grants back. Supabase is making exposure opt-in: the new default began rolling out gradually to new projects on May 30, 2026, and is scheduled for existing projects on October 30, 2026, but in existing projects, tables that already exist keep their current grants.

    How to test

    List the grants with the query below and compare each line with what your app needs. Revoke what's extra, for example revoke insert, update, delete on table public.<table> from anon;, in the same migration as the table's RLS and policies.

    select table_name, grantee,
           string_agg(privilege_type, ', ' order by privilege_type) as privileges
    from information_schema.role_table_grants
    where table_schema = 'public' and grantee in ('anon', 'authenticated')
    group by table_name, grantee
    order by table_name, grantee;

    Source: Supabase docs: Securing your API

  • Why it matters and how to test it

    Why it matters

    This is the view from outside: copy the URL and key from the page, then call the REST API directly. If a private table answers your curl with rows, it answers anyone's.

    How to test

    Find the project URL and key in your own app (browser network tab or built bundle). Request each table that holds user data with the first command. An empty array [] or a permission error (code 42501) passes; rows are a finding. Then sign in as a second test user, copy their access token from the Authorization header in the network tab, and repeat with the second command to check that one user can't see another's rows.

    # As a signed-out visitor
    curl 'https://PROJECT_REF.supabase.co/rest/v1/profiles?select=*&limit=5' \
      -H "apikey: PUBLISHABLE_OR_ANON_KEY"
    
    # As signed-in test user B (their access token, not the key, goes in Authorization)
    curl 'https://PROJECT_REF.supabase.co/rest/v1/profiles?select=*&limit=5' \
      -H "apikey: PUBLISHABLE_OR_ANON_KEY" \
      -H "Authorization: Bearer USER_B_ACCESS_TOKEN"

    Source: Supabase docs: Build an API route in less than 2 minutes

  • Why it matters and how to test it

    Why it matters

    Advisors are deterministic checks that ship with the platform, and they catch most of what this checklist covers: tables without RLS (lint 0013), always-true policies (0024), policies that read user_metadata (0015), views that bypass RLS (0010), user data exposed through a view (0002), sensitive columns exposed (0023), public buckets that allow listing (0025), and SECURITY DEFINER functions callable by signed-out or signed-in users (0028, 0029).

    How to test

    Open Security Advisor in Studio, or run supabase db advisors from the CLI. Treat ERROR-level findings as release blockers and re-run the advisor after every schema change. Supabase itself notes some findings may be intentional, so check each one against how your app is supposed to work before changing anything.

    supabase db advisors

    Source: Supabase docs: Advisors

[02]

The Lovable-era exposure pattern

AI app builders made a powerful architecture mainstream: a React frontend that queries Supabase straight from the browser with the public key. Nothing sits between a visitor and the database except your policies. When a table ships without RLS, or with a policy written to make a feature work rather than to decide who may see it, anyone who copies the key from the page can read, and sometimes write, that table. In May 2025 the pattern got a CVE record for Lovable-generated sites, CVE-2025-48757: 'An insufficient database Row-Level Security policy in Lovable through 2025-04-15 allows remote unauthenticated attackers to read or write to arbitrary database tables of generated sites.' NVD lists a CVSS 3.1 base score of 9.3 (Critical) from MITRE. Lovable disputes the record, on the grounds that each customer of the platform accepts responsibility for protecting their application's data. Either way the fix lives in your project, and the checks below apply to any Supabase app whose frontend talks to the database directly, whichever tool wrote it.

  • Why it matters and how to test it

    Why it matters

    An always-true policy makes RLS look switched on while letting the named role reach every row. Supabase spells it out: a policy for anon with using (true) grants every unauthenticated visitor read access to every row the role can reach through its grants. Security Advisor flags these as lint 0024.

    How to test

    List every policy with the query below. Look for qual or with_check equal to true, insert and update policies with an empty with_check, and policies whose roles are {public} or {anon} on tables that hold private data.

    select tablename, policyname, cmd, roles, qual, with_check
    from pg_policies
    where schemaname in ('public', 'storage')
    order by tablename, cmd;

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    with check is what stops a user creating a row that belongs to someone else, and on update it stops them reassigning user_id to another account. Supabase also notes that an update needs a matching select policy to behave as expected.

    How to test

    In the policy listing, confirm each INSERT and UPDATE row has a with_check that references auth.uid() (or your tenant check). Then, as test user B, insert a row carrying user A's user_id, and update one of B's own rows to set user_id to A. Both should fail with 42501.

    create policy "Users update own profile"
    on public.profiles for update
    to authenticated
    using ( (select auth.uid()) = user_id )
    with check ( (select auth.uid()) = user_id );

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    An 'update your own profile' policy authorizes the row, not the column. If permission or billing data lives on a row its owner can update, the owner can upgrade themselves. Supabase recommends keeping roles in a dedicated table, and column-level privileges can limit which columns a role may update.

    How to test

    For each table users can update, list the columns that affect permissions or billing. As an ordinary signed-in user, try the request below; it should fail or change nothing. Fix it by moving those columns to a table users can't write to, or with column grants: revoke update on table public.profiles from authenticated; grant update (display_name, avatar_url) on table public.profiles to authenticated;.

    curl -X PATCH 'https://PROJECT_REF.supabase.co/rest/v1/profiles?id=eq.YOUR_USER_ID' \
      -H "apikey: PUBLISHABLE_OR_ANON_KEY" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -H "Prefer: return=representation" \
      -d '{"role":"admin"}'

    Source: Supabase docs: Column Level Security

  • Why it matters and how to test it

    Why it matters

    When users sign in somewhere Supabase doesn't know about, the database never receives a user token, so policies that check the user match nothing and every query comes back empty. The tempting fixes, disabling RLS or querying with the secret key, make the data public. Supabase supports Clerk, Firebase Auth, Auth0, AWS Cognito and WorkOS as third-party auth providers, so RLS can see the signed-in user.

    How to test

    Check whether the app signs users in with a non-Supabase library. If it does, confirm a Third-Party Auth integration exists in the Dashboard, that RLS is still enabled on user tables (first check), and that no client code creates a Supabase client with a secret or service_role key (see the key check below).

    Source: Supabase docs: Third-party auth

  • Why it matters and how to test it

    Why it matters

    While 'Allow new users to sign up' is on, anyone can create an account with your public key, so to authenticated using (true) is close to public. Anonymous users also get the authenticated role; Supabase says to check the is_anonymous claim, using restrictive policies so the check always applies.

    How to test

    Review the Auth settings for Allow new users to sign up, Confirm email and Allow anonymous sign-ins. Search your policies for to authenticated paired with using (true) on private tables. If anonymous sign-ins are on, add a restrictive policy to writes that need a real account, like the one below.

    create policy "Only permanent users can post"
    on public.posts as restrictive for insert
    to authenticated
    with check ( (select (auth.jwt()->>'is_anonymous')::boolean) is false );

    Source: Supabase docs: Anonymous Sign-Ins

[03]

Policies that say who, not just whether

  • Why it matters and how to test it

    Why it matters

    Supabase recommends always naming the role, so a policy stops at to authenticated for anonymous requests. auth.uid() returns null when nobody is signed in, and null = user_id is false, which denies access by accident rather than by design. Explicit policies are also easier for the next person, or the next AI prompt, to edit safely.

    How to test

    In the policy listing, flag rows whose roles are {public}. Rewrite them in the form below.

    create policy "Users read own todos"
    on public.todos for select
    to authenticated
    using ( (select auth.uid()) = user_id );

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    Supabase: raw_user_meta_data can be updated by the signed-in user, so it isn't a good place to store authorization data, while raw_app_meta_data can't be updated by the user. A policy that trusts user_metadata ->> 'role' lets users hand themselves the role. Security Advisor flags it as lint 0015.

    How to test

    Search your policies for user_metadata with the query below, and search your SQL functions and migrations for the same string.

    select tablename, policyname
    from pg_policies
    where qual ilike '%user_metadata%' or with_check ilike '%user_metadata%';

    Source: Supabase docs: Row Level Security

[04]

Side doors: views, functions and schema visibility

  • Why it matters and how to test it

    Why it matters

    Views bypass RLS by default because they run with their creator's rights, so a view over a protected table hands out every row its policies were meant to hold back. A public view over auth.users exposes your users' personal data (lint 0002), and views that bypass RLS are lint 0010. Materialized views can't apply RLS at all, so keep them out of exposed schemas (lint 0016).

    How to test

    List the views and materialized views in public with the query below. Any plain view without security_invoker=true in its options that reads protected tables is a finding: alter view public.<view> set (security_invoker = true);.

    select c.relname as view_name, c.relkind, c.reloptions
    from pg_class c
    join pg_namespace n on n.oid = c.relnamespace
    where n.nspname = 'public' and c.relkind in ('v', 'm');

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    RLS doesn't apply to functions. A SECURITY DEFINER function runs with its owner's privileges, and on Supabase the owner is usually postgres, which bypasses RLS. Any function in an exposed schema that a role can execute is callable at /rest/v1/rpc/<name>. Supabase's advice is never to create one in an exposed schema, and to pin search_path on every one.

    How to test

    Run the query below. Every true under anon_can_execute or auth_can_execute needs a decision. To close one, revoke execute (revoke execute on function public.<fn>(<args>) from anon, authenticated, public;), move the function to a schema the API doesn't expose, or switch it to SECURITY INVOKER. Advisor lints 0028 and 0029 flag these too.

    select p.proname as function_name,
           pg_get_function_identity_arguments(p.oid) as args,
           has_function_privilege('anon', p.oid, 'execute') as anon_can_execute,
           has_function_privilege('authenticated', p.oid, 'execute') as auth_can_execute,
           p.proconfig as settings
    from pg_proc p
    join pg_namespace n on n.oid = p.pronamespace
    where n.nspname = 'public' and p.prosecdef;

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    A list of tables and columns takes the guesswork out of an attack. Supabase has been closing this by default: under its published schedule, the OpenAPI spec at /rest/v1/ has answered only secret (and legacy service_role) keys since March 11, 2026 for new projects and April 8, 2026 for existing ones. pg_graphql is no longer enabled automatically on new projects, and pg_graphql 1.6.0 turns introspection off by default for projects created from June 29, 2026. Older projects keep their GraphQL behaviour until they change it, and pg_graphql shows any table a role can select from, whatever your RLS says (lints 0026 and 0027).

    How to test

    Request the OpenAPI spec with only the public key (first command). It should return an 'Access to schema is forbidden' error, not a description of your tables. Then check Database > Extensions for pg_graphql and disable it if your app doesn't use GraphQL. If it does, run the second command with only the public key. On a project that doesn't need introspection, it should return an error, not a list of your tables.

    # REST schema: expect "Access to schema is forbidden"
    curl 'https://PROJECT_REF.supabase.co/rest/v1/' \
      -H "apikey: PUBLISHABLE_OR_ANON_KEY"
    
    # GraphQL introspection: expect an error, not your type names
    curl -X POST 'https://PROJECT_REF.supabase.co/graphql/v1' \
      -H "apikey: PUBLISHABLE_OR_ANON_KEY" \
      -H 'Content-Type: application/json' \
      --data-raw '{"query":"{ __schema { types { name } } }"}'

    Source: Supabase changelog: Breaking change in pg_graphql 1.6.0, GraphQL introspection disabled by default

[05]

Keys and server code

  • Why it matters and how to test it

    Why it matters

    A secret key bypasses every Row Level Security policy, so a leaked one exposes all of your project's data. New secret keys refuse browser requests (Supabase checks the User-Agent and returns 401), but an attacker can still use a leaked key from any other tool. Legacy keys are long JWTs starting with eyJ, and the role inside tells you which one you're looking at.

    How to test

    Search your build output and repository with the first command, and check git history too. For any eyJ... key you find, decode its middle segment in the browser console with the second snippet: anon is expected, service_role is a critical finding. If a secret key ever shipped, delete or rotate it in Settings > API Keys immediately.

    grep -rnE "sb_secret_|service_role" dist/ build/ .next/static/ src/ 2>/dev/null
    
    // Browser console: read the role inside a legacy JWT key
    JSON.parse(atob('PASTE_MIDDLE_SEGMENT'.replace(/-/g, '+').replace(/_/g, '/'))).role

    Source: Supabase docs: API keys

  • Why it matters and how to test it

    Why it matters

    Code using the secret key runs as service_role, which bypasses RLS, so any query it makes for a user has to filter by that user itself. Supabase's Edge Functions guide warns that a handler which queries a shared table with the admin client, without filtering by the caller's ID, returns every user's rows.

    How to test

    Find every place a secret-key client is created (search for SUPABASE_SECRET_KEY, SERVICE_ROLE and supabaseAdmin). For each query, confirm the user ID comes from the verified token, never from the request body. Where the work is on the caller's behalf, prefer a user-scoped client so RLS applies.

    Source: Supabase docs: Securing Edge Functions

  • Why it matters and how to test it

    Why it matters

    verify_jwt is on by default and rejects requests without a valid user JWT. Turning it off to clear a 401 during development removes that check. With the new API keys, the platform check also accepts publishable and secret keys, and Supabase says the check alone doesn't authenticate a caller that sends only an API key, so authorization belongs in your code.

    How to test

    Search supabase/config.toml for verify_jwt = false and review each function it names. Call every function with no credentials using the second command; anything other than a 401 or a deliberately public response is a finding. Then call it with only the publishable key in the apikey header, as the third command does. verify_jwt lets that request through, so unless the function is deliberately public, your handler has to answer 401 or 403 itself. Webhook endpoints should reject an unsigned request.

    grep -n -B1 "verify_jwt = false" supabase/config.toml
    
    # No credentials: expect 401
    curl -i -X POST 'https://PROJECT_REF.supabase.co/functions/v1/FUNCTION_NAME' \
      -H 'Content-Type: application/json' -d '{}'
    
    # Publishable key only: passes verify_jwt, so your handler must reject it
    curl -i -X POST 'https://PROJECT_REF.supabase.co/functions/v1/FUNCTION_NAME' \
      -H "apikey: PUBLISHABLE_KEY" \
      -H 'Content-Type: application/json' -d '{}'

    Source: Supabase docs: Authorization headers (Edge Functions)

[06]

Storage and Realtime

  • Why it matters and how to test it

    Why it matters

    A public bucket skips access control for reading: anyone with a file's URL can fetch it. That suits avatars and blog images, not IDs, invoices or exports. A broad SELECT policy on a public bucket also lets clients enumerate every file name in it (lint 0025).

    How to test

    Run the query below and confirm every public bucket only holds files you'd be happy to see on your homepage. Then review storage rows in the policy listing from the previous section.

    select id, public from storage.buckets order by public desc, id;

    Source: Supabase docs: Storage Buckets

  • Why it matters and how to test it

    Why it matters

    Storage permissions are RLS policies on storage.objects. A policy that only checks bucket_id hands every signed-in user every file in that bucket. Supabase's pattern ties the first folder in the path to the user: (storage.foldername(name))[1] = (select auth.jwt()->>'sub').

    How to test

    Sign in as test user B and try to list and download user A's folder with the snippet below. Expect an empty list and an error.

    const { data: files } = await supabase.storage.from('documents').list('USER_A_ID')
    // expect []
    const { error } = await supabase.storage.from('documents').download('USER_A_ID/statement.pdf')
    // expect an error

    Source: Supabase docs: Storage Access Control

  • Why it matters and how to test it

    Why it matters

    Supabase only enforces private channels once the public access setting is disabled. A private channel's access policies are checked when a client joins and then cached for the connection, so a user whose access you revoke keeps receiving Broadcast and Presence messages until their token expires or a new one is sent; Supabase advises keeping the JWT expiry short. Postgres Changes is checked separately: it sends a row only to clients whose RLS policies on that table allow them to read it.

    How to test

    Check Realtime Settings for 'Allow public access'. Confirm clients join with { config: { private: true } } and that the policy listing includes policies on realtime.messages. Then join a private topic as a user who shouldn't have access and confirm you receive nothing.

    const channel = supabase.channel('room:123', { config: { private: true } })

    Source: Supabase docs: Realtime Authorization

[07]

Keep it closed

  • Why it matters and how to test it

    Why it matters

    In Supabase's words, until the suite passes you don't know whether the policies do what you intended. A denial by a using clause raises no error, it just matches zero rows, so tests need returning and a follow-up read to prove a denied write left the row intact.

    How to test

    Create a test file per table with supabase test new <table>_rls.test, switch identity with set local role and set local request.jwt.claim.sub, and run supabase test db locally and in CI. Studio's user impersonation and the RLS tester preview are handy for quick manual checks, but they don't replace the suite.

    -- supabase/tests/profiles_rls.test.sql
    begin;
    select plan(2);
    
    insert into auth.users (id, email) values
      ('11111111-1111-1111-1111-111111111111', '[email protected]'),
      ('22222222-2222-2222-2222-222222222222', '[email protected]');
    
    -- Seed the owner's row while still running as postgres, so 'reads none' proves something
    insert into profiles (id, user_id, avatar_url)
    values (gen_random_uuid(), '11111111-1111-1111-1111-111111111111', 'owner.png');
    
    set local role authenticated;
    set local request.jwt.claim.sub = '22222222-2222-2222-2222-222222222222';
    
    select is_empty(
      $$ select * from profiles where user_id = '11111111-1111-1111-1111-111111111111' $$,
      'another user reads none of the owner''s profile'
    );
    select throws_ok(
      $$ insert into profiles (id, user_id, avatar_url)
         values (gen_random_uuid(), '11111111-1111-1111-1111-111111111111', 'x.png') $$,
      '42501', null,
      'another user cannot create a profile for the owner'
    );
    
    select * from finish();
    rollback;

    Source: Supabase docs: Row Level Security

  • Why it matters and how to test it

    Why it matters

    Supabase recommends bundling grants with the RLS setup in the same migration: grants control which roles reach a table, RLS and policies control which rows. For AI tools that create tables, Supabase suggests updating the tool's system prompt or adopting its agent skill, which includes the grants step. A policy that only exists in the Dashboard isn't in code review, isn't in your other environments and isn't covered by tests.

    How to test

    Confirm supabase/migrations/ contains the RLS, grant and policy statements for every table. Run the policy listing query on staging and production and compare the two.

    -- One migration: RLS, grants and policies together
    alter table public.invoices enable row level security;
    revoke all on table public.invoices from anon, authenticated;
    grant select, insert, update on table public.invoices to authenticated;
    
    create policy "Owners read invoices"
    on public.invoices for select
    to authenticated
    using ( (select auth.uid()) = user_id );

    Source: Supabase docs: Securing your API

  • Why it matters and how to test it

    Why it matters

    RLS protects data from your app's users. These settings protect the database connection and your own account, and slow down automated sign-up abuse.

    How to test

    Work through the Security section of Supabase's Production Checklist: SSL enforcement and network restrictions under Database settings, MFA for your Supabase account and organization, email confirmations in the Auth provider settings, and Auth CAPTCHA.

    Source: Supabase docs: Production Checklist

[FAQs]

Frequently asked questions

Is it safe for my Supabase key to be in my frontend code?

The publishable key (or the legacy anon key) is designed to be public: Supabase says anyone can read it, so it only reaches what Row Level Security allows. The secret key (or legacy service_role key) is the opposite, because it bypasses RLS and must never leave your servers. Supabase is deprecating the legacy anon and service_role keys by the end of 2026, so this is also a good moment to move to publishable and secret keys.

What is CVE-2025-48757, and does it affect my app?

It's a CVE record published in May 2025 describing insufficient Row-Level Security in Lovable-generated sites through 2025-04-15, which let unauthenticated visitors read or write database tables. Lovable disputes it, saying each customer is responsible for protecting their own app's data. Whether or not your app was built in Lovable, if your frontend talks to Supabase directly, the first two sections of this checklist are where to start: they test for exactly that exposure.

Supabase changed its defaults in 2026. Am I already covered?

Partly. New tables in new projects are no longer exposed to the Data API automatically (rolling out to new projects since May 30, 2026), and the same change is scheduled for existing projects on October 30, 2026, but tables that already exist keep their current grants. Under Supabase's schedule, the OpenAPI schema endpoint has answered only secret keys since April 8, 2026, and pg_graphql is now opt-in on new projects. None of this changes how RLS behaves, so an existing table with RLS off or an always-true policy is exactly as open as it was.

Lovable already runs a security scan when I publish. Isn't that enough?

It's a good first line. Lovable's Quick scan runs on every publish and flags things like tables without row-level security and access rules that let everyone through, and its Deep scan reviews application code. Lovable's own documentation also says these tools don't replace a thorough security review, and suggests an additional professional review for apps that handle sensitive data or critical functions.

Why does my query return an empty array instead of an error?

Because that's how a policy says no. A missing grant raises a permission error (42501) before any policy runs, but a policy that matches no rows just returns an empty result. If the app shows no data after you enable RLS, check grants first, then policies, and resist switching RLS off or reaching for the secret key to make the screen load.

I only have an hour. What should I do first?

Run the RLS-enabled query, the outside-in curl test and the always-true policy query, then search your bundle for a secret key. Those four checks cover the exposure behind CVE-2025-48757 and the mistakes that need no skill to find.

[Sources]

Sources

Every check links to the documentation behind it. All 27 sources below were opened on Oct 7, 2026.

  1. Supabase: Row Level Security Supabase (docs) · Undated docs page, current as of access date
  2. Supabase: Securing your API Supabase (docs) · Undated docs page, current as of access date
  3. Supabase changelog: Breaking Change: Tables not exposed to Data and GraphQL API automatically (Apr 28, 2026) Supabase (docs) · Published 2026-04-28
  4. Supabase: Build an API route in less than 2 minutes Supabase (docs) · Undated docs page, current as of access date
  5. Supabase: Advisors Supabase (docs) · Undated docs page, current as of access date
  6. Supabase splinter (official lint definitions): 0024 permissive_rls_policy, 0002 auth_users_exposed, 0028 anon_security_definer_function_executable, 0026 pg_graphql_anon_table_exposed Supabase (GitHub, official repo) · Fetched from main branch on access date
  7. NVD: CVE-2025-48757 NIST National Vulnerability Database · Last modified 2026-06-17
  8. CVE.org: CVE-2025-48757 CVE Program · Record updated 2025-08-21
  9. Lovable: Security overview Lovable (vendor docs) · Undated docs page, current as of access date
  10. Supabase: Column Level Security Supabase (docs) · Undated docs page, current as of access date
  11. Supabase: Third-party auth Supabase (docs) · Undated docs page, current as of access date
  12. Supabase: Anonymous Sign-Ins Supabase (docs) · Undated docs page, current as of access date
  13. Supabase: General configuration (Auth) Supabase (docs) · Undated docs page, current as of access date
  14. Supabase changelog: Breaking Change: Removing access to OpenAPI spec via the anon key (Feb 17, 2026) Supabase (docs) · Published 2026-02-17
  15. Supabase changelog: Breaking Change: pg_graphql no longer enabled automatically (Jan 26, 2026) Supabase (docs) · Published 2026-01-26
  16. Supabase changelog: Breaking change in pg_graphql 1.6.0, GraphQL introspection disabled by default Supabase (docs) · Published 2026-05-25, edited 2026-06-13
  17. Supabase: API keys Supabase (docs) · Undated docs page, current as of access date
  18. Supabase: Securing Edge Functions Supabase (docs) · Undated docs page, current as of access date
  19. Supabase: Authorization headers (Edge Functions) Supabase (docs) · Undated docs page, current as of access date
  20. Supabase: Storage Buckets Supabase (docs) · Undated docs page, current as of access date
  21. Supabase: Storage Access Control Supabase (docs) · Undated docs page, current as of access date
  22. Supabase: Realtime Authorization Supabase (docs) · Undated docs page, current as of access date
  23. Supabase: Testing Your Database Supabase (docs) · Undated docs page, current as of access date
  24. Supabase changelog: Feature Preview: RLS Tester (Apr 24, 2026) Supabase (docs) · Published 2026-04-24
  25. Supabase: Production Checklist Supabase (docs) · Undated docs page, current as of access date
  26. PostgreSQL: pg_policies view PostgreSQL Global Development Group · Current docs
  27. PostgreSQL: pg_tables view PostgreSQL Global Development Group · Current docs