-- 0002: pentest remediation (A4/W3 privilege reduction, A3 quota default, W1 subscription rows) BEGIN; -- --------------------------------------------------------------------------- -- A4 / W3: authenticated users must NOT be able to UPDATE tunnels directly. -- All legitimate writes (claim, token rotation, quota/usage, activation) go -- through service-role server routes / workers. A direct grant let an owner -- tamper with bytes_used, quota_bytes, is_active, token and subdomain. -- --------------------------------------------------------------------------- REVOKE UPDATE ON public.tunnels FROM authenticated; DROP POLICY IF EXISTS tunnels_update_own ON public.tunnels; -- SELECT (read-only dashboard) stays intact via tunnels_select_own. -- --------------------------------------------------------------------------- -- A3: free-tier quota default 1 TiB -> 2 GiB, and shrink existing rows that -- still carry the old default so the kill-switch is meaningful. -- --------------------------------------------------------------------------- ALTER TABLE public.tunnels ALTER COLUMN quota_bytes SET DEFAULT 2147483648; UPDATE public.tunnels SET quota_bytes = 2147483648 WHERE quota_bytes = 1099511627776; -- --------------------------------------------------------------------------- -- W1 (enablement): ensure every user has a subscriptions row so the billing -- webhook activation (PATCH by user) actually targets a row, and backfill -- existing users. -- --------------------------------------------------------------------------- CREATE OR REPLACE FUNCTION public.handle_new_user() RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ BEGIN INSERT INTO public.users_profile (user_id, email) VALUES (NEW.id, NEW.email) ON CONFLICT (user_id) DO NOTHING; INSERT INTO public.subscriptions (user_id, plan, status) VALUES (NEW.id, 'free', 'active') ON CONFLICT (user_id) DO NOTHING; RETURN NEW; END; $$; REVOKE ALL ON FUNCTION public.handle_new_user() FROM PUBLIC; GRANT EXECUTE ON FUNCTION public.handle_new_user() TO supabase_auth_admin; INSERT INTO public.subscriptions (user_id, plan, status) SELECT id, 'free', 'active' FROM auth.users ON CONFLICT (user_id) DO NOTHING; COMMIT;