diff --git a/supabase/migrations/020_swarm_runner_registry.sql b/supabase/migrations/020_swarm_runner_registry.sql index d23ba8a..f797f0c 100644 --- a/supabase/migrations/020_swarm_runner_registry.sql +++ b/supabase/migrations/020_swarm_runner_registry.sql @@ -189,6 +189,6 @@ $$; ALTER TABLE public.task_runners ENABLE ROW LEVEL SECURITY; --- Admins can read runner status for observability +-- Service role can read runner status; later migrations add super-admin observability. CREATE POLICY "task_runners_select" ON public.task_runners - FOR SELECT USING (true); + FOR SELECT TO service_role USING (true); diff --git a/supabase/migrations/036_file_attachments.sql b/supabase/migrations/036_file_attachments.sql index 319eb83..d113b30 100644 --- a/supabase/migrations/036_file_attachments.sql +++ b/supabase/migrations/036_file_attachments.sql @@ -58,11 +58,11 @@ CREATE POLICY "Users can delete own workspace attachments" -- Service role (task runner) can read/insert attachments CREATE POLICY "Service role can read attachments" - ON public.file_attachments FOR SELECT + ON public.file_attachments FOR SELECT TO service_role USING (true); CREATE POLICY "Service role can insert attachments" - ON public.file_attachments FOR INSERT + ON public.file_attachments FOR INSERT TO service_role WITH CHECK (true); -- ─── Storage bucket ───────────────────────────────────────────────────────── diff --git a/supabase/migrations/040_team_memory_search.sql b/supabase/migrations/040_team_memory_search.sql index ad10722..fa07623 100644 --- a/supabase/migrations/040_team_memory_search.sql +++ b/supabase/migrations/040_team_memory_search.sql @@ -60,4 +60,4 @@ CREATE POLICY "team_memory_delete" ON public.team_memory -- ──────────────────────────────────────────────────────────────────────────── CREATE POLICY "team_memory_insert_service" ON public.team_memory - FOR INSERT WITH CHECK (true); + FOR INSERT TO service_role WITH CHECK (true); diff --git a/supabase/migrations/062_knowledge_base.sql b/supabase/migrations/062_knowledge_base.sql index 45c8af7..22a700b 100644 --- a/supabase/migrations/062_knowledge_base.sql +++ b/supabase/migrations/062_knowledge_base.sql @@ -121,7 +121,7 @@ CREATE POLICY "knowledge_chunks_select" ON public.knowledge_chunks -- Insert/delete by service role (processing pipeline) — service role bypasses RLS CREATE POLICY "knowledge_chunks_insert" ON public.knowledge_chunks - FOR INSERT WITH CHECK (true); + FOR INSERT TO service_role WITH CHECK (true); CREATE POLICY "knowledge_chunks_delete" ON public.knowledge_chunks FOR DELETE USING (public.is_workspace_member(workspace_id)); diff --git a/supabase/migrations/071_chat_widget.sql b/supabase/migrations/071_chat_widget.sql index 0642f39..a009676 100644 --- a/supabase/migrations/071_chat_widget.sql +++ b/supabase/migrations/071_chat_widget.sql @@ -71,7 +71,7 @@ CREATE POLICY chat_sessions_workspace_read ON chat_sessions -- Service role bypass for task runner writes CREATE POLICY chat_sessions_service_write ON chat_sessions - FOR ALL + FOR ALL TO service_role USING (true) WITH CHECK (true); diff --git a/supabase/migrations/078_google_connections.sql b/supabase/migrations/078_google_connections.sql index 2c49ff8..fd9e059 100644 --- a/supabase/migrations/078_google_connections.sql +++ b/supabase/migrations/078_google_connections.sql @@ -40,7 +40,7 @@ CREATE POLICY "google_connections_workspace_access" -- Service role can read/write (for Edge Functions + task runner) CREATE POLICY "google_connections_service_role" - ON public.google_connections FOR ALL + ON public.google_connections FOR ALL TO service_role USING (true) WITH CHECK (true); diff --git a/supabase/migrations/082_harden_service_role_rls_policies.sql b/supabase/migrations/082_harden_service_role_rls_policies.sql new file mode 100644 index 0000000..70cc05a --- /dev/null +++ b/supabase/migrations/082_harden_service_role_rls_policies.sql @@ -0,0 +1,60 @@ +-- SPDX-License-Identifier: AGPL-3.0-or-later +-- Copyright (C) 2026 CrewForm +-- +-- 082_harden_service_role_rls_policies.sql +-- +-- Tighten policies that were intended for trusted backend/service-role writes. +-- Without an explicit TO clause, PostgreSQL policies apply to PUBLIC, which can +-- make Supabase anon/authenticated clients eligible for the policy. + +-- Chat widget sessions: workspace members keep the separate read policy; +-- trusted backend writes are limited to service_role. +DROP POLICY IF EXISTS chat_sessions_service_write ON public.chat_sessions; +CREATE POLICY chat_sessions_service_write + ON public.chat_sessions + FOR ALL TO service_role + USING (true) + WITH CHECK (true); + +-- Google OAuth tokens: only service role should read/write token material. +DROP POLICY IF EXISTS "google_connections_service_role" ON public.google_connections; +CREATE POLICY "google_connections_service_role" + ON public.google_connections + FOR ALL TO service_role + USING (true) + WITH CHECK (true); + +-- File attachment metadata: workspace policies handle user access; service +-- access is limited to the task runner/backend. +DROP POLICY IF EXISTS "Service role can read attachments" ON public.file_attachments; +CREATE POLICY "Service role can read attachments" + ON public.file_attachments + FOR SELECT TO service_role + USING (true); + +DROP POLICY IF EXISTS "Service role can insert attachments" ON public.file_attachments; +CREATE POLICY "Service role can insert attachments" + ON public.file_attachments + FOR INSERT TO service_role + WITH CHECK (true); + +-- Team memory and knowledge chunks are inserted by backend pipelines. +DROP POLICY IF EXISTS "team_memory_insert_service" ON public.team_memory; +CREATE POLICY "team_memory_insert_service" + ON public.team_memory + FOR INSERT TO service_role + WITH CHECK (true); + +DROP POLICY IF EXISTS "knowledge_chunks_insert" ON public.knowledge_chunks; +CREATE POLICY "knowledge_chunks_insert" + ON public.knowledge_chunks + FOR INSERT TO service_role + WITH CHECK (true); + +-- Runner status should not be public. Service-role task runner access bypasses +-- RLS; super admins can still read status for observability. +DROP POLICY IF EXISTS "task_runners_select" ON public.task_runners; +CREATE POLICY "task_runners_select" + ON public.task_runners + FOR SELECT TO authenticated + USING (public.is_super_admin());