Supabase supautils force-grants PUBLIC EXECUTE on new public objects: fleet REVOKE-explicit standing pattern + live-exposure sweep
Root cause (db-pluto-cc live-verified via 3 disposable postgres-owned probe fns, audit-pluto-ca PASS, from PLUTO-612): Supabase's supautils.hint_roles platform GUC (sighup-level, unchangeable by ANY db role incl postgres, not disableable from SQL) force-grants PUBLIC EXECUTE on every new public-schema function REGARDLESS of ALTER DEFAULT PRIVILEGES ... REVOKE ON FUNCTIONS — that default-privilege revoke is effectively a NO-OP on Supabase. LIVE-EXPOSURE EDGE: any existing SECURITY DEFINER fn reading secrets/vault that relied on the default-privilege revoke is currently PUBLIC/anon/authenticated-callable = exfil hole. Scope: (A) CODIFY in evolutiva-db.md via coder-mars-cc (pluto drafts): every migration creating OR replacing a public fn must include explicit SAME-TRANSACTION REVOKE ALL/EXECUTE FROM PUBLIC, anon, authenticated + explicit grants only to intended roles; CREATE OR REPLACE gets the same rule (reviewers cannot assume signature pre-existed); do NOT rely on ALTER DEFAULT PRIVILEGES as future-proofing; prefer SECURITY INVOKER where caller already holds grants (removes the class). Correct migration-057-style misleading future-proofing docs so agents don't trust them. (B) PER-APP LIVE SWEEP (mars/pluto/venus, +enamel): audit live public fns created after each app's default-privilege-revoke migration for residual PUBLIC/anon/authenticated EXECUTE; remediate with explicit revoke; prioritize SECURITY DEFINER fns touching secrets/vault. Mars already confirmed clean (cron_auth_header ACL {postgres,service_role}, mig 019 explicit revoke + INVOKER guard). Pluto 080 fixed only fn_drain_email_outbox_if_due — rest of pluto unswept. (C) OBJECT-CLASS PROBE: dispatch controlled disposable probes for NEW public TABLE + SEQUENCE grants per app; if supautils also re-grants PUBLIC on those, extend the same-migration explicit REVOKE rule + static guard BY OBJECT CLASS. (D) Add a migration static guard/checklist + post-apply catalog assertion (per-app lint) so this is enforced, not oral knowledge. Children: per-app sweep+probe WIs (mars/pluto/venus/enamel); commons codification via coder-mars-cc.
Sub-tickets — 3/3 done
Questions
Activity
-
Commons codification DONE: coder-mars-cc landed §'Supabase supautils Force-Grants PUBLIC EXECUTE' in shared/md/evolutiva-db.md, SHA ef00815, placed after §Secret-Returning SECURITY DEFINER Functions as the GENERAL rule (secret-returning three-way REVOKE = its special case), keeps the pre-2026-05-30 broad-grant reconcile. Per-app children dispatched same-day: MARS-522, PLUTO-614, VENUS-288, ENAMEL-10. Venus running urgent-first check on fn_drainEmailOutboxGuard (venus51 DEFINER/vault, shipped ~05:17) — highest live risk. Enamel greenfield (near-zero live fns expected). Object-class (table/sequence) probe verdicts + per-app sweep counts pending; commons 'open extension' line to tighten once all probes report.
-
RESOLVED + de-escalated (Elazar 2026-07-19: Supabase Data API/PostgREST DISABLED on all Evolutiva projects -> PUBLIC/anon grants have no reachable HTTP path -> hygiene, not a live hole; don't overbuild). Final findings: (a) supautils force-grants PUBLIC EXECUTE on NEW public FUNCTIONS only, per-project — reproduces on mars/pluto/enamel, NOT venus; explicit same-tx REVOKE is the fix, works everywhere. (b) TABLES/SEQUENCES NOT force-granted on any project; enamel's greenfield table grants were stock un-hardened Supabase defaults (confirmed by post-hardening re-probe coming up clean), fixed one-time (REVOKE ALL + ALTER DEFAULT PRIVILEGES), not per-migration. (c) INVOKER is secondary mitigation not a class-removal; REVOKE is primary. (d) CoR on hardened fn keeps ACL; only new fn-name is force-granted. Sweeps: mars/pluto/venus 0 residual, enamel greenfield 0 — all CLEAN. Deliverable = commons note evolutiva-db.md §supautils (coder-mars-cc, SHA 3ebca8e + Data-API-context edit pending), framed defense-in-depth hygiene. Lint-tooling (MARS-523 static guard + post-apply assertion) STOOD DOWN per Elazar as overbuild for a non-reachable surface — commons note is the whole deliverable, fn REVOKE stays a habit not a gitpush gate. Per-app children closed: MARS-522, PLUTO-614, VENUS-288, ENAMEL-10. Enamel additionally baked a one-time table hardening + catalog health-check into enamel-commons (its own No-RLS baseline, not fleet-mandated).
-
Commons note FINAL SHA = de4d076 (Data-API-disabled context line landed). MARS-523 closed won't-build (never started, zero waste). All 4 sweep children closed clean. EVO-71 = hygiene rule, resolved.