Summary
The sessions table SELECT policy is USING (true) with no role restriction. Every row — including is_private = true invite-only sessions — is readable by anyone, even unauthenticated users, revealing private session titles, descriptions, mentor identities, and scheduling details.
Evidence
supabase/migrations/20260617000000_consolidate_rls_policies.sql:
CREATE POLICY "Anyone can view sessions"
ON public.sessions FOR SELECT USING (true);
No TO clause means it applies to both anon and authenticated. The private-session work (20260724000000_secure_private_sessions.sql) only gated join_session and session messages — the row itself stays world-readable (confirmed by the author's note in 20260801000000_fix_messages_rls_private_sessions.sql).
Exploit
-- via PostgREST /rest/v1/sessions?select=title,description,mentor_id,timing,is_private
select title, description, mentor_id, is_private from public.sessions; -- no auth needed
Impact
- Existence and details of private/invite-only sessions leaked to anonymous users.
- Mentor availability and schedule exposed; enables targeted harassment or unsolicited joining attempts (join itself is gated, but enumeration is not).
Suggested Fix
- Drop
Anyone can view sessions.
- Add an
anon-deny policy.
- Add an
authenticated SELECT policy that allows:
is_private = false sessions (public), plus
- sessions where
mentor_id = auth.uid(), or the user is in session_invites, or the user is in session_participants.
Summary
The
sessionstable SELECT policy isUSING (true)with no role restriction. Every row — includingis_private = trueinvite-only sessions — is readable by anyone, even unauthenticated users, revealing private session titles, descriptions, mentor identities, and scheduling details.Evidence
supabase/migrations/20260617000000_consolidate_rls_policies.sql:No
TOclause means it applies to bothanonandauthenticated. The private-session work (20260724000000_secure_private_sessions.sql) only gatedjoin_sessionand session messages — the row itself stays world-readable (confirmed by the author's note in20260801000000_fix_messages_rls_private_sessions.sql).Exploit
Impact
Suggested Fix
Anyone can view sessions.anon-deny policy.authenticatedSELECT policy that allows:is_private = falsesessions (public), plusmentor_id = auth.uid(), or the user is insession_invites, or the user is insession_participants.