Build1 publisherNot yet confirmed elsewhere2 min readPublished
Supabase ends automatic role grants on new tables in existing projects from October 30
Supabase stops auto-granting anon, authenticated and service_role on new tables in existing projects on October 30, an auditor writing on dev.to reports. Tables created after that need scoped grants in their migrations, since the common GRANT ALL TO public shortcut lets anonymous callers back in.
The Engineer · Build desk

What happened
- A table created after the cutoff without an explicit GRANT returns error 42501, permission denied, through the Data API, even when called with service_role.
- Late migrations, tenant-per-table schemes and admin "add table" flows are the code paths the auditor expects to break.
- The auditor warns that search results and AI coding tools will suggest GRANT ALL TO public as the quick fix for the error.
- The post supplies a query on information_schema.role_table_grants that lists every grant held by anon, authenticated and PUBLIC in the public schema.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision Apps that create tables at runtime, such as per-tenant tables or admin add-table screens, now have to issue the grant in that same code path or ship a feature that fails on first use.
- exposure Teams that accept the AI-suggested GRANT ALL TO public patch swap a visible outage for a table the anon key can reach, guarded only by whatever RLS policies happen to exist.
- constraint Verifying the new grants needs tests that set real JWT claims, because SET ROLE authenticated alone leaves auth.uid() NULL and ownership policies filter out every row.
Postgres runs two separate checks before a row leaves Supabase's Data API. The calling role needs a privilege on the table, and row level security has to admit the row. The service_role key bypasses all RLS [12], yet a missing grant produces the 42501 error for that role too [2]. Skipping the second check does nothing about a failed first one [14]. Until October 30, Supabase supplied the table privilege for anon, authenticated and service_role on every new table [1].
The account comes from an auditor who says they review AI-built apps for a living and drew every example from anonymized public repos [8]. The post cites Supabase changelog 45329 for the date and scope but does not quote the entry [1].
GRANT ALL TO public is a bad repair because of who public is. In Postgres, public includes anon [9]. A public grant puts the anon key past the first check, and RLS becomes the only control left on the table [15].
The same post shows how often that control is open. A policy written FOR SELECT USING (true) with no TO clause applies to public, so the anon key reads the whole table [9]. On one marketplace the author audited, that policy sat on a profiles table with every user's email in it [10]. Of a policy titled to sound restrictive, the author wrote: "The policy name says "Users can read all profiles"; the name doesn't execute anything." [13]
The post's recommended pattern is a grant per role, written into the migration beside the table. Authenticated gets select, insert, update and delete, and anon gets nothing unless the table is truly public [5]. I think this is the right default for any team that reviews its migrations. The privilege ships in the same file as the table it protects, so anon access shows up as one line in the diff [5].
Tables that exist today are the less obvious risk. The post tells readers to find tables that currently rely on auto-grants and give them explicit grants before October 30 [7]. A migration that drops and recreates one of those tables after the date creates a new table. Under the change, that table comes back with no grants for any of the three roles [17].
What to watch
- The text of Supabase changelog 45329, to confirm the auditor's stated scope: existing projects, new tables only, and all three roles.
- Whether AI coding tools start generating migrations with per-role grants, or keep proposing GRANT ALL TO public when users paste a 42501 error.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence50
- Adoption
- Insufficient
- Hype gap+10
- Incentives55
- Confidence55
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
On October 30, 2026, Supabase stops auto-granting anon, authenticated and service_role on new tables in existing projects, citing Supabase changelog 45329.
- [2]
A table created after October 30 without an explicit GRANT returns 42501 permission denied through the Data API, even for service_role.
- [3]
Apps that create tables after that date, through late migrations, tenant-per-table schemes or an admin 'add table' flow, break with a permission error.
- [4]
The quick fix that search results and AI tools will suggest is GRANT ALL ... TO public, which re-opens the exposure the change exists to prevent.
- [5]
The safe pattern is scoped grants per role written into the migration next to the table: grant select, insert, update, delete on public.my_table to authenticated, and explicitly not to anon unless the table is truly public.
- [6]
A check query selects grantee, table_name and privilege_type from information_schema.role_table_grants where table_schema = 'public' and grantee is anon, authenticated or PUBLIC.
- [7]
Readers should look for tables they want accessible that currently rely on auto-grants, which will need explicit grants before Oct 30, and for broad PUBLIC grants that should not exist.
- [8]
The author says they audit AI-built apps for a living; all examples come from real audits of shipped apps this month and are drawn from public repos, anonymized.
- [9]
A policy written FOR SELECT USING (true) with no TO clause applies to public in Postgres, which includes anon, so the table is fully readable with the anon key.
- [10]
A marketplace the author audited had such a policy on its profiles table, with every user's email in it.
- [11]
Tests must switch to authenticated with a real JWT claim set; SET ROLE authenticated alone leaves auth.uid() NULL and every ownership policy filtering everything.
- [12]
The service_role key bypasses all RLS.
- [13]
The policy name says "Users can read all profiles"; the name doesn't execute anything.
- [14]
Table privileges and RLS are separate checks: service_role bypasses RLS yet still fails with 42501 when the table grant is missing.
- [15]
A GRANT ALL ... TO public reaches anon, leaving RLS as the only control between the anon key and the table.
- [16]
Apps that create tables at runtime must issue the grant in the same code path, because a table created after October 30 without an explicit grant fails with 42501.
- [17]
A migration that drops and recreates an existing table after October 30 creates a new table, which falls under the change and returns without auto-granted access for anon, authenticated or service_role.
Sources
1 independent publisher whose own reporting we read for this story.
- dev.toAI Built Your Supabase App and It Works. Here's What Breaks Next.
1 article · October 7, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.