supabase-rls-policies
Skill41k starsChanged 21 days agoMITView on GitHub
Write, review, and test Supabase Row Level Security (RLS) policies so that one user cannot read or change another user''s rows. Use when creating or changing tables, policies, views, or security definer functions in a Supabase project, when reviewing a migration that touches RLS, or when asked to prove user isolation with pgTAP tests that sign in as two users.
Trending
More talk lately.about the whole repository
Who's talking about github/awesome-copilot
- Software Developer Diaries“What are Skills, Agents, Prompts, Instructions and how to use them?”YouTube · Mar 28, 2026 · 78k views
- James Montemagno“Manage Agents, Instructions, Prompts, & Skills in Seconds with this VS Code Extension”YouTube · Dec 20, 2025 · 33k views
- TechWhistle“10 GitHub Copilot Tricks Most Developers Don't Know (2026)”YouTube · Apr 1, 2026 · 31k views
- GitHub Daily Trend AI Podcast“GitHub - github/awesome-copilot: Community-contributed instructions, prompts, and configurations ...”YouTube · Oct 2, 2025 · 532 views
- Next Horizon“awesome-copilot: AI Coding Assistance with Community Agents & Plugins”YouTube · Oct 17, 2026 · 152 views
The biggest 5 of 90 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 90
Talked about on Bluesky, GitHub, YouTube, Hacker News and the web (90 times).
On Bluesky · 41
- Jul 2, 2025Less vibes, more standards. Custom instructions, prompts, and chat modes for Copilot → github.com/github/aweso... — @vscode.dev28 likes and reposts
- Aug 20, 2025I did an overhaul of the Awesome Copilot README to make it easier to install the prompts, instructions, and chat modes to VS Code - there… — @aaron-powell.com14 likes and reposts
- Jul 31, 2025Fixed a bug on github.com/github/aweso... so you can now one-click add Chat Modes to your VS Code environment (it worked for prompts and… — @aaron-powell.com5 likes and reposts
- Jul 1, 2025Community-contributed instructions, prompts, and configurations to help you make the most of GitHub Copilot. github.com/github/aweso... — @garrytrinder.dev5 likes and reposts
- Jul 3, 2025Want GitHub Copilot to follow the most modern best practices in your language of choice? Guide it with custom instructions, starting from… — @pamelafox.bsky.social4 likes and reposts
36 more on Bluesky
- Oct 1, 2026📦 github / awesome-copilot ⭐ 39,586 (+59) 🗒 JavaScript Community-contributed instructions, agents, skills, and configurations to help you… — @github-trending-js.bsky.social3 likes and reposts
- Mar 5, 2026It's honestly been a lot of a trial and error for me. I did do some training at work but applying it to real-world problems and picking the… — @adamrdriscoll.com3 likes and reposts
- Dec 11, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 13,991 (+111) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social3 likes and reposts
- Oct 23, 2025📦 github / awesome-copilot ⭐ 10,301 (+73) 🗒 JavaScript Community-contributed instructions, prompts, and configurations to help you make… — @github-trending-js.bsky.social3 likes and reposts
- Sep 25, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 8,027 (+102) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social3 likes and reposts · 1 reply
- Jul 4, 2025👀 Check this :A community-powered repo to enhance your GitHub Copilot experience > shared prompts, instructions, and configs so Copilot… — @elbruno.com3 likes and reposts
- Sep 24, 2026📦 github / awesome-copilot ⭐ 39,304 (+43) 🗒 JavaScript Community-contributed instructions, agents, skills, and configurations to help you… — @github-trending-js.bsky.social2 likes and reposts
- Aug 26, 2026📦 github / awesome-copilot ⭐ 38,267 (+44) 🗒 JavaScript Community-contributed instructions, agents, skills, and configurations to help you… — @github-trending-js.bsky.social2 likes and reposts
- Mar 7, 2026github / awesome-copilot Community-contributed instructions, prompts, and configurations to help you make the most of GitHub Copilot.… — @pythonhub.dev2 likes and reposts
- Mar 1, 2026Community-curated collection of specialized agents, instructions, and workflows that transform GitHub Copilot from basic autocomplete into… — @arifsolmaz.bsky.social2 likes and reposts
- Feb 26, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 22,634 (+146) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social2 likes and reposts
- Jan 10, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 16,762 (+165) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending.bsky.social2 likes and reposts
- Dec 2, 2025📦 github / awesome-copilot ⭐ 13,317 (+77) 🗒 JavaScript Community-contributed instructions, prompts, and configurations to help you make… — @github-trending-js.bsky.social2 likes and reposts
- Nov 19, 2025Awesome GitHub Copilot Customizations github.com/github/aweso... — @adamrdriscoll.com2 likes and reposts
- Nov 7, 2025📦 github / awesome-copilot ⭐ 11,436 (+79) 🗒 JavaScript Community-contributed instructions, prompts, and configurations to help you make… — @github-trending-js.bsky.social2 likes and reposts
- Oct 9, 2025I've enrolled the Awesome Copilot repo for #Hacktoberfest, so if you want to join the challenge, you now can with github.com/github/aweso... — @aaron-powell.com2 likes and reposts
- Nov 3, 2026📦 github / awesome-copilot ⭐ 40,747 (+52) 🗒 JavaScript Community-contributed instructions, agents, skills, and configurations to help you… — @github-trending-js.bsky.social1 likes and repost · 1 reply
- Oct 28, 2026📦 github / awesome-copilot ⭐ 40,463 (+45) 🗒 JavaScript Community-contributed instructions, agents, skills, and configurations to help you… — @github-trending-js.bsky.social1 likes and repost · 1 reply
- Sep 11, 2026📦 github / awesome-copilot ⭐ 38,893 (+53) 🗒 JavaScript Community-contributed instructions, agents, skills, and configurations to help you… — @github-trending-js.bsky.social1 likes and repost
- Mar 17, 2026Vous connaissez peut être le repository Github awesome-copilot (github.com/github/aweso...) contenant des skills, prompts, etc. pour Github… — @devdevdev.net1 likes and repost
- Feb 20, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 21,816 (+133) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Feb 5, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 20,129 (+137) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Jan 28, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 19,270 (+147) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Jan 15, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 17,630 (+180) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Dec 31, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 15,940 (+100) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Dec 20, 2025🚀 Skyrocketing! 🚀 (200+ new stars) 📦 github / awesome-copilot ⭐ 14,836 (+217) 🗒 JavaScript Community-contributed instructions, prompts,… — @github-trending.bsky.social1 likes and repost
- Dec 19, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 14,605 (+172) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Dec 6, 2025📦 github / awesome-copilot ⭐ 13,645 (+52) 🗒 JavaScript Community-contributed instructions, prompts, and configurations to help you make… — @github-trending-js.bsky.social1 likes and repost
- Nov 23, 202511월의 남은 쿼터를 소진하기 위한 작업은 Chatmode + Agent 지원방법에 대한 공부. 이번달은 대부분 직접 코딩하거나, GPT5-mini를 사용했기 때문에 Sonnet 펑펑 돌리면서 공부해도 되겠다. Chatmode 기반으로 작업할때는… — @luncliff.bsky.social1 likes and repost
- Nov 12, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 11,788 (+110) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Nov 1, 2025🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 10,993 (+115) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social1 likes and repost
- Oct 1, 2025📦 github / awesome-copilot ⭐ 8,546 (+91) 🗒 JavaScript Community-contributed instructions, prompts, and configurations to help you make… — @github-trending.bsky.social1 likes and repost
- Sep 23, 2025Join the AMA at 4PM SF time, here: discord.gg/YZbkuKb3?eve... Check out the awesome-copilot repo, here: github.com/github/aweso... — @nonfamous.bsky.social1 likes and repost · 1 reply
- Aug 15, 2025Shape Copilot to your workflow. Use the Awesome-Copilot repo’s custom instructions, reusable prompts, and chat modes to get AI suggestions… — @martinrojas.dev1 likes and repost
- Jul 2, 2025Awesome GitHub Copilot Customizations github.com/github/aweso... #GitHub #Copilot #GitHubCopilot — @yzhums.bsky.social1 likes and repost
- Jan 22, 2026🔥 Hot Repo! 🔥 (100+ new stars) 📦 github / awesome-copilot ⭐ 18,469 (+149) 🗒 JavaScript Community-contributed instructions, prompts, and… — @github-trending-js.bsky.social0 likes and reposts · 1 reply
On GitHub · 34
- Apr 12, 2026[Bug]: `npx skills update <skill-name>` adds all other skills from the skill repo — vercel-labs/skills46 reactions · 8 comments
- Jul 9, 2025Support for *.instructions.md files in IntelliJ for project-scoped Copilot customization — microsoft/copilot-intellij-feedback25 reactions · 9 comments
- Apr 26, 2026[Bug]: `npx skills update` downloads entire repository instead of specific skill when using subpaths — vercel-labs/skills6 reactions · 4 comments
- Jul 16, 2026docs(agent-skills): point the public catalog at the public org — chainguard-dev/edu2 reactions · 3 comments
- Jun 21, 2026[Feature]: Is there a way to specify .github/skills as the install location for skills? — vercel-labs/skills2 reactions
29 more on GitHub
- Oct 31, 2025Links to awesome-copilot are broken and result in 404 — github/docs2 reactions · 2 comments
- Oct 30, 2026feat(skills): add public Git installation to the CLI — alex-de-haas/docker-host1 reaction · 2 comments
- Oct 28, 2026docs(skills): correct the [dependabot skip] wording in the dependabot skill — docdyhr/mcp-wordpress1 reaction · 3 comments
- Sep 25, 2026Unblock learning-hub activation job by bumping blocked gh-aw compile version — Vbddr/awesome-copilot1 reaction · 1 comment
- Sep 24, 2026Automate agent package releases — socialbu/socialbu-agent1 reaction · 13 comments
- Sep 20, 2026fix(deps): clear Critical Dependabot alert for astro — Wicked-Sick-Ltd/awesome-copilot1 reaction
- Sep 20, 2026fix(security): CodeQL clear-text storage + hostBridge allowlist (#1–#2) — Wicked-Sick-Ltd/awesome-copilot1 reaction
- Sep 10, 2026Create Skill.md — 1napz/crystalcastleX1 reaction
- Sep 4, 2026fix(plugin): conform manifest to Agent Plugins 1.0.0 — BigCactusLabs/blotter1 reaction · 1 comment
- Aug 31, 2026fix(agents): launch Droid at High autonomy in yolo mode — stablyai/orca1 reaction · 3 comments
- Aug 21, 2026chore(skills): awesome-copilot update candidate 83561bd7 — KraineOpasen/bukerov-twitch-miner-go1 reaction
- Aug 10, 2026Bundled github-issues skill documents an unsafe shell-quoting pattern, and its locus is a synced file — devantler-tech/agent-plugins1 reaction · 1 comment
- Jul 23, 2026Plugin plan — charlyautomatiza/playwright-plugin1 reaction
- Jun 9, 2026Problem with the description length on using `az boards work-item create` — Azure/azure-cli1 reaction · 4 comments
- May 26, 2026[BUG] Unable to specify Skills/Agents when installing via the UI — runkids/skillshare1 reaction · 1 comment
- May 16, 2026[Ensure Agent skills follow the standards] — ralphke/Agentic-Coding1 reaction · 3 comments
- Apr 13, 2026Simplify, transfer/reorganize `.github/copilot-instructions.md` into `AGENTS.md` and other more appropriate agent context files — huanshankeji/compose-multiplatform-html-unified1 reaction
- Apr 9, 2026[broken-links] Broken external links detected (2 confirmed 404s) — htekdev/gh-aw-overview1 reaction
- Mar 31, 2026Add the awesome-copilot repo-architect agent to this repository — derecskey/valleypaintingco1 reaction
- Mar 22, 2026Add createagents.md skill — sparkfabrik/sf-agents-harness1 reaction
- Mar 22, 2026Code architecture inspection — davidamitchell/Research1 reaction
- Mar 10, 2026Git fatal: destination path error due to Windows long paths in Extensions view — microsoft/vscode1 reaction
- Mar 4, 2026Migrate to copilot-sdk — george-cz/ai-plan-comparator1 reaction
- Feb 26, 2026Create .NET package to collect and summarize Azure Skills for an Azure Service — diberry/microsoft-mcp-doc-generation1 reaction
- Feb 12, 2026ai-agents repository is showing 0 available in Marketplace — rjmurillo/skill-installer1 reaction · 3 comments
- Feb 6, 2026Add plugins for other Microsoft owned MCPs (Docs, playwright, etc). — github/copilot-plugins1 reaction · 2 comments
- Dec 25, 2025リポジトリ内の全ファイルの日本語への翻訳 — yamayuski/awesome-copilot1 reaction
- Dec 20, 2025Agent Capability Gaps: Comparison with awesome-copilot — rjmurillo/ai-agents1 reaction · 4 comments
- Oct 19, 2025File protocol handler for installing custom instructions, prompts, and chat modes — github/CopilotForXcode1 reaction
On YouTube · 5
- Mar 28, 2026What are Skills, Agents, Prompts, Instructions and how to use them? — Software Developer Diaries78k views · 29 comments
- Dec 20, 2025Manage Agents, Instructions, Prompts, & Skills in Seconds with this VS Code Extension — James Montemagno33k views · 12 comments
- Apr 1, 202610 GitHub Copilot Tricks Most Developers Don't Know (2026) — TechWhistle31k views · 14 comments
- Oct 2, 2025GitHub - github/awesome-copilot: Community-contributed instructions, prompts, and configurations ... — GitHub Daily Trend AI Podcast532 views
- Oct 17, 2026awesome-copilot: AI Coding Assistance with Community Agents & Plugins — Next Horizon152 views · 1 comment
On Hacker News · 5
- Nov 11, 2025Copilot modes you probably didn't know exist4 points · 1 comment
- Aug 10, 2025Awesome-copilot: Community-contributed instructions, prompts, and configurations3 points
- Feb 17, 2026Rug – Repeat Until Good1 point
- Dec 22, 2025Gilfoyle code review agent skill that roasts your code1 point
- Oct 28, 2025GitHub Copilot Customizations1 point
On the web · 5
- Sep 7, 2026awesome-copilot - The management layer for AI agent skills — tessl.io
- Aug 21, 2026Awesome GitHub Copilot - Sébastien Dubois — dsebastien.net
- Apr 6, 2026Gerald Versluis' Post — linkedin.com
- Mar 16, 2026Awesome GitHub Copilot just got a website, and a learning ... — developer.microsoft.com
- Mar 6, 2026Awesome Copilot Sync — marketplace.visualstudio.com
In this repository490 other files it gives its agents.
- AGENTS.mdAGENTS.md
- skills/foundry-agentic-loop/evals/fixtures/improve-history/AGENTS.mdAGENTS.md
- skills/foundry-agentic-loop/evals/fixtures/rapid-locked/AGENTS.mdAGENTS.md
- skills/foundry-agentic-loop/evals/fixtures/sdd-deployed/AGENTS.mdAGENTS.md
- skills/foundry-agentic-loop/evals/fixtures/sdd-paused/AGENTS.mdAGENTS.md
- skills/foundry-agentic-loop/evals/fixtures/team-conventions/AGENTS.mdAGENTS.md
- skills/repo-standardizer/templates/AGENTS.mdAGENTS.md
- skills/setup-my-iq/assets/templates/AGENTS.mdAGENTS.md
- skills/repo-standardizer/templates/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- agentic-workflowsSkill
- code-reviewSkill
- create-canvas-extensionSkill
- acquire-codebase-knowledgeSkill
- acreadiness-assessSkill
- acreadiness-generate-instructionsSkill
- acreadiness-policySkill
- ad-campaign-analyzerSkill
- add-educational-commentsSkill
- adobe-illustrator-integrationsSkill
- adobe-illustrator-scriptingSkill
- agent-architectureSkill
- agent-governanceSkill
- agentic-evalSkill
- agent-owasp-complianceSkill
- agent-skill-stackSkill
- agent-supply-chainSkill
- ai-prompt-engineering-safety-reviewSkill
- ai-readySkill
- ai-team-orchestrationSkill
- anti-ui-slopSkill
- api-breaking-change-detectorSkill
- appinsights-instrumentationSkill
- apple-appstore-reviewerSkill
- architecture-blueprint-generatorSkill
- arch-linux-triageSkill
- arduino-azure-iot-edge-integrationSkill
- arize-ai-provider-integrationSkill
- arize-annotationSkill
- arize-datasetSkill
- arize-evaluatorSkill
- arize-experimentSkill
- arize-instrumentationSkill
- arize-linkSkill
- arize-prompt-optimizationSkill
- arize-traceSkill
- aspireSkill
- aspnet-minimal-api-openapiSkill
- audit-integritySkill
- automate-thisSkill
- autoresearchSkill
- aws-cdk-python-setupSkill
- aws-cloudwatch-investigationSkill
- aws-cost-optimizeSkill
- aws-resource-health-diagnoseSkill
- aws-resource-querySkill
- aws-well-architected-reviewSkill
- az-cost-optimizeSkill
- azure-architecture-autopilotSkill
- azure-container-registry-cliSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 30
Run alter table ... enable row level security on every table in an exposed schema.
- Very specific: line 31
Add a to clause to every policy.
- Very specific: line 68
Never base a policy on user_metadata (raw_user_meta_data).
- Distinctive: line 106
Never create one in an exposed schema.
- Very specific: line 192
Use returning on writes. An update or delete that RLS filters out succeeds with zero rows, so only the returned rows show what happened.
- Very specific: line 196
Add an anon case for any table that anonymous visitors must not read, and add one to the plan count.
- Very specific: line 207
If your project does not grant table privileges to anon, the read raises 42501 instead, so use throws_ok.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Supabase RLS Policies
Write Row Level Security (RLS) policies for Supabase tables, then prove them with pgTAP tests that act as two different users. A policy is not finished until a test shows that a second user cannot read, change, delete, or create rows that belong to the first user.
When to Use This Skill
- Creating a table in an exposed schema (by default
public) - Adding or changing a policy, a view, or a
security definerfunction - Reviewing a migration or pull request that touches RLS
- Answering whether users or tenants are isolated from each other
Workflow
- List the access rules first. For each table, write down which role (
anonorauthenticated) may run which operation (select,insert,update,delete) on which rows. Confirm the list with the user before writing SQL. Each rule gets one test. - Write the migration. Enable RLS, add one policy per operation, and index every column the policies filter on.
- Write a pgTAP test file for the table under
supabase/tests/, using the template below. - Run
supabase test dband read every line of output. - Break the policy on purpose, on a local database only. Copy the test file and add a temporary policy with
using (true)right afterbegin;, for examplecreate policy "tmp_open" on public.notes for select to authenticated using (true);. Runsupabase test dbagainst the local stack fromsupabase start, confirm at least one test fails, then delete the copy. Do the same with a temporaryfor updateand afor deletepolicy. The file ends withrollback, so the temporary policy is undone even when the run fails or stops early. Never put a temporary policy in a migration, and never run this against a shared or production database. Do not drop the real policy to do this: with no policy every read is denied, so denial tests still pass and prove nothing. - Do not change a policy just to make a test pass. Report which assertion failed and which policy it covers, and let the user decide which one is wrong.
Rules for Every Table
Enable RLS and name the role
- Run
alter table ... enable row level securityon every table in an exposed schema. Once RLS is on and no policy exists, the API returns no rows. - Add a
toclause to every policy. Without it the policy applies toPUBLIC, which means every role, includinganon. auth.uid()returnsnullwhen the request has no signed in user.to authenticatedkeeps anonymous requests from reaching the check at all.
One policy per operation, with the owner checked on writes
alter table public.notes enable row level security;
create policy "notes_select_own" on public.notes
for select to authenticated
using ((select auth.uid()) = owner_id);
create policy "notes_insert_own" on public.notes
for insert to authenticated
with check ((select auth.uid()) = owner_id);
create policy "notes_update_own" on public.notes
for update to authenticated
using ((select auth.uid()) = owner_id)
with check ((select auth.uid()) = owner_id);
create policy "notes_delete_own" on public.notes
for delete to authenticated
using ((select auth.uid()) = owner_id);
create index notes_owner_id_idx on public.notes using btree (owner_id);usingchecks rows that already exist.with checkchecks the row being written. Rows that failusingare skipped with no error; a row that failswith checkraises an error.- Bind the owner column in every insert and update check. A check such as
auth.uid() is not nullonly proves the caller is signed in. Any signed in user can then insert a row with another user's id in the owner column. - A column default such as
default auth.uid()does not protect the owner column. Postgres uses a default only when the insert does not supply a value, and the client can always supply one. - An
updateneeds a matchingselectpolicy, or the update will not work as expected. - Wrap
auth.uid()andauth.jwt()in(select ...)so Postgres runs them once per statement instead of once per row. - Index every column a policy filters on. A column counts as indexed only when it is the first column of a btree index.
Authorization data in the token
- Never base a policy on
user_metadata(raw_user_meta_data). Signed in users can change it themselves. - Store roles, teams, and plans in
app_metadata(raw_app_meta_data), which users cannot change, and read it withauth.jwt(). - A change to
app_metadatareachesauth.jwt()only after the user's token is refreshed. A user removed from a team keeps access until then.
Multi factor authentication
To require a second factor, add a restrictive policy:
create policy "notes_require_aal2" on public.notes
as restrictive
for all to authenticated
using ((select auth.jwt()->>'aal') = 'aal2');Restrictive policies only narrow access. A table with only restrictive policies returns no rows, so keep the permissive policies above.
Views
Views bypass RLS by default because they run with the rights of the role that created them. On Postgres 15 and later, create views with security_invoker = true:
create view public.my_notes
with (security_invoker = true)
as select id, body from public.notes;On older versions, remove every grant path or keep the view in a schema that is not exposed. Revoking only the direct grants is not enough: a grant to PUBLIC, a grant to a role the API roles are members of, or a grant on a single column still lets them read the view. Check the result with has_any_column_privilege, which counts all three; relacl lists only direct table grants.
revoke all on public.my_notes from public, anon, authenticated;
select has_any_column_privilege('anon', 'public.my_notes', 'select'),
has_any_column_privilege('authenticated', 'public.my_notes', 'select'); -- both must be falseSecurity definer functions
- A
security definerfunction runs as its owner. If the owner ispostgres, it bypasses RLS. - Never create one in an exposed schema. It can be called over the Data API with the owner's rights.
- Set
search_path = ''and schema qualify every name inside the function.
Keys
- Secret keys (and the legacy
service_rolekey) bypass RLS. Use them only on a server, never in a browser or mobile app. - A secret key bypasses RLS only when the request has no user access token. If the request carries one, that user's policies apply.
Two User pgTAP Test Template
Save as supabase/tests/notes_rls_test.sql and adapt the table, columns, and ids. The file runs in one transaction and rolls back, so test data never persists.
begin;
create extension if not exists pgtap with schema extensions;
select plan(8);
-- Two users, created before switching roles.
insert into auth.users (id, email) values
('11111111-1111-1111-1111-111111111111', 'user1@test.com'),
('22222222-2222-2222-2222-222222222222', 'user2@test.com');
insert into public.notes (id, owner_id, body) values
('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', '11111111-1111-1111-1111-111111111111', 'user 1 note');
-- As user 1: the owner can read and change their own row.
set local role authenticated;
set local request.jwt.claims = '{"sub": "11111111-1111-1111-1111-111111111111", "role": "authenticated"}';
select results_eq(
$$select body from public.notes where id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'$$,
$$values ('user 1 note'::text)$$,
'user 1 reads their own note'
);
select results_eq(
$$update public.notes set body = 'edited' where id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' returning body$$,
$$values ('edited'::text)$$,
'user 1 updates their own note'
);
-- As user 2: every attempt on user 1's row must fail.
-- User 2 owns no rows yet, so the write probes need no where clause.
set local request.jwt.claims = '{"sub": "22222222-2222-2222-2222-222222222222", "role": "authenticated"}';
select is_empty(
$$select 1 from public.notes where id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'$$,
'user 2 cannot read user 1 note'
);
select is_empty(
$$update public.notes set body = 'changed' returning 1$$,
'user 2 cannot update user 1 note'
);
select is_empty(
$$delete from public.notes returning 1$$,
'user 2 cannot delete user 1 note'
);
select throws_ok(
$$insert into public.notes (owner_id, body) values ('11111111-1111-1111-1111-111111111111', 'forged')$$,
'42501', null,
'user 2 cannot create a note owned by user 1'
);
select results_eq(
$$insert into public.notes (owner_id, body) values ('22222222-2222-2222-2222-222222222222', 'user 2 note') returning owner_id$$,
$$values ('22222222-2222-2222-2222-222222222222'::uuid)$$,
'user 2 creates their own note'
);
-- No where clause: the update policy alone picks user 2's row,
-- so only its with check can stop the transfer.
select throws_ok(
$$update public.notes set owner_id = '11111111-1111-1111-1111-111111111111'$$,
'42501', null,
'user 2 cannot hand their note to user 1'
);
select * from finish();
rollback;Notes on the template:
- Use
returningon writes. An update or delete that RLS filters out succeeds with zero rows, so only the returned rows show what happened. - In user 2's update and delete probes, do not filter on a column or return one. When an update or delete reads a column, Postgres applies the
selectpolicy as well, so a correctselectpolicy can hide anupdateordeletepolicy that is too open. Return the constant1and rely on user 2 owning no rows yet. - Filter reads by the ids the test inserted. A count over the whole table breaks once other data exists.
- Error
42501is the code Postgres raises when a written row fails awith checkexpression. Add an
anoncase for any table that anonymous visitors must not read, and add one to the plan count. Replace the claims first: changing the role does not clear them, soauth.uid()would still return user 2's id.set local request.jwt.claims = '{"role": "anon"}'; set local role anon; select is_empty( $$select 1 from public.notes where id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'$$, 'an anonymous visitor cannot read user 1 note' );If your project does not grant table privileges to
anon, the read raises42501instead, so usethrows_ok.
Testing Policies That Read Other Claims
The template sets the whole claims object in request.jwt.claims, the setting PostgREST fills from the token. auth.uid() and auth.jwt() both read it. If a test sets only request.jwt.claim.sub, auth.uid() still works but auth.jwt() returns null, so a policy that compares a claim such as aal or a value in app_metadata sees null. The aal2 policy above denies every user in that state, so a test that expects a denial passes for the wrong reason.
For a table with the restrictive aal2 policy, add "aal": "aal2" to the claims at both user switches in the template, so the owner checks still pass. Then test the other side before select * from finish();, and add these two assertions to the plan count:
-- If the anon case ran first, the SQL role is still anon. The role claim in the JSON does not change it.
set local role authenticated;
set local request.jwt.claims = '{"sub": "11111111-1111-1111-1111-111111111111", "role": "authenticated", "aal": "aal1"}';
select is_empty(
$$select 1 from public.notes where id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'$$,
'an aal1 session cannot read user 1 note'
);
set local request.jwt.claims = '{"sub": "11111111-1111-1111-1111-111111111111", "role": "authenticated", "aal": "aal2"}';
select isnt_empty(
$$select 1 from public.notes where id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'$$,
'an aal2 session reads user 1 note'
);Review Checklist
- RLS is enabled on every table in an exposed schema
- Every policy names a role with
to - Insert and update checks bind the owner column to
(select auth.uid()) - No policy reads
user_metadata - Views use
security_invoker = true, or are not exposed - Security definer functions live outside exposed schemas and set
search_path = '' - Each policy column has an index that leads with that column
- Each user data table has a two user test covering read, update, delete, and insert
- The second user's update and delete probes read no column
- Tests set the full
request.jwt.claimsobject at each user switch, and replace it before theanoncase - The suite fails when a temporary
using (true)policy is added inside the test transaction on a local database
References
- Row Level Security, Supabase docs
- Test Row Level Security policies with pgTAP, Supabase docs
- Multi-Factor Authentication, Supabase docs
- CREATE POLICY, PostgreSQL docs
- Transactions, PostgREST docs (
request.jwt.claims) - CREATE TABLE, PostgreSQL docs (column defaults)
- auth.uid() source and auth.jwt() source, Supabase Auth
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

