Proposal: detect read policies whose USING is unconditionally true for unauthenticated sessions (inverted auth.* IS NULL disjunct)
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 45/100
Direzione di ricerca
Inizia con lo skill /new-lint e il lint esistente 0024_rls_policy_always_true, quindi esamina il contratto standard dei lint e la struttura dei test pg_regress. Conferma il nuovo numero del lint e la scelta tra WARN/INFO prima di procedere. Il lavoro è completo quando viene rilevato il vero positivo proposto e i negativi elencati—current_user, IS NULL condizionato da AND, un predicato con ambito limitato e current_setting(name, false)—rimangono non rilevati nei test di regressione.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Hi! A suggestion for a new Security lint, related to but framed differently from PR #28 ("feat: add lint to detect RLS policies that allow access to anonymous users").
The gap
0024_rls_policy_always_true deliberately scopes its always-true USING check to command in ('UPDATE','DELETE','ALL') and matches only the literal forms ('true','(true)','1=1','(1=1)') — with the comment that SELECT … USING (true) is often intentional. That's the right call for literal true. But a very common real-world shape slips through entirely:
create policy "read own"
on public.documents for select to authenticated
using ( auth.uid() is null or owner_id = auth.uid() );
For any request where auth.uid() is NULL (an anonymous session, or any token-less call), auth.uid() is null is true, so the whole USING is true and every row is readable. It isn't literal-true, and it's a SELECT, so 0024 can't see it — yet it exposes the table.
Why this isn't the PR #28 discussion
This lint does not flag "the policy is reachable by anonymous users" — that's a deliberate design choice and not inherently a bug (which, as I read it, was the substance of the pushback on PR #28). It flags a predicate whose top-level OR short-circuits to true for any session where the auth function returns NULL — a logic error that is wrong whether or not anonymous sign-ins are enabled. (Which sessions those are depends on the policy's roles: for a public/anon policy it's any token-less request; for a TO authenticated policy it's the narrower case of an authenticated token with a NULL sub.) An … IS NULL OR … disjunct on an auth function almost always means the author intended the negation (IS NOT NULL AND …) or a scoped check, and accidentally turned the policy into a no-op. Framing it as a correctness defect (rather than an anonymous-access judgement) keeps it squarely in advisor territory.
Proposed detection
A pure SQL view over pg_policies, standard lint contract. It fires on a predicate shape, not on any project setting, so it needs no conditional execution:
- permissive policy,
cmd in ('SELECT','ALL'), granted toanon/authenticated/public; - normalized
qualcontains a top-levelORdisjunct of the form<auth fn>() is null, where<auth fn>is genuinely nullable —auth.uid()/auth.jwt()/auth.role(), orcurrent_setting('…', true). - Exclusions, to stay false-positive-clean: never-NULL identity functions (
current_user/session_user/current_role/user) — those disjuncts are constant-false dead branches, not leaks; andcurrent_setting(name)/current_setting(name, false), which raise rather than return NULL. - Severity:
WARN/INFO; remediation: "remove theIS NULLdisjunct, or replace it with an explicit deny."
A couple of questions before a PR
- Would you prefer a fresh lint number, or to revive/rework PR #28?
- Severity preference —
WARNorINFO?
Happy to implement it with the /new-lint skill + pg_regress tests covering the true positive above plus negatives (current_user is null disjunct, AND-gated is null, a plain scoped predicate, current_setting(name, false) is null).
- Lingua principale
- PLpgSQL
- Stelle
- 284
- Fork
- 110
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di supabase/splinter
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 69/100
supabase/splinter#206 · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
0002_auth_users_exposed false positive: pg_depend join lacks a refclassid filter (cross-catalog OID collision)Forse già presa @tushardev-365 l’ha presa 97 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 40/100
supabase/splinter#210 · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
0030_autovacuum_disabled misses tables where autovacuum_enabled is set to off, 0 or noForse già presa @RaphaelFakhri l’ha presa 9 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
-
Proposal: lint for RLS policies whose role lacks the table privilege (policy_without_privilege)Forse già presa @larik15 l’ha presa 29 giorni fa. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 1/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di supabase/splinter
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
formbricks/formbricks#9918 ·
I maintainer di solito rispondono entro 1 giorno
-
2022 2023 AR
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
PolicyEngine/policyengine-taxsim#1506 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
open-metadata/OpenMetadata#36946 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
meta-llama/PurpleLlama#273 ·