conversions
Supabase Security Conversions
Conversions are for builders who want to go from “this is exposed” to “this is locked down” with minimal guesswork. Use these when you need a repeatable path and clear verification.
What a “conversion” means in Supabase security
These pages are utilities: they help you convert an unsafe access state into a safer one.
Each conversion includes:
- A clear from/to state
- Step-by-step conversion logic
- Example conversions
- Related conversions to apply next
Supabase security conversions you can apply
| Conversion | From → To | URL |
|---|---|---|
| Convert a public RPC to service_role-only | A Postgres function can be executed by PUBLIC/anon/authenticated via Supabase RPC. → Function EXECUTE is restricted and only backend code can call it using service_role. | /conversions/public-rpc-to-service-role-only |
| Convert a public Storage bucket to private + signed URLs | Bucket is public or listable; objects can be discovered or downloaded directly. → Bucket is private; downloads only via short-lived signed URLs after authorization checks. | /conversions/public-bucket-to-private-signed-urls |
| Convert a public table to backend-only access | Table is readable/writable from anon/authenticated clients (direct REST queries succeed). → Table is not directly accessible from client roles; access only through server endpoints using service_role. | /conversions/public-table-to-backend-only |
Safety rule: change application paths before revoking access
Conversions often fail because teams revoke access first and then scramble to restore app behavior.
A safer order is:
- Add backend endpoints that perform the needed reads/writes with authorization.
- Switch the frontend to use the backend endpoint (feature flag if needed).
- Only then: revoke direct client grants / public bucket access / public RPC execution.
- Run verification: direct access should fail; backend path should succeed.
Recommended order (highest risk first)
- Convert public tables to backend-only access.
- Convert public storage buckets to private + signed URLs.
- Convert public RPC to service_role-only execution.
- Add a repeatable checklist to prevent regressions.
How to validate a conversion worked
- Direct access with client credentials should fail.
- Backend endpoints should succeed for authorized users.
- Re-scan and confirm the finding disappears.
- Add a regression test or checklist query to catch drift.
Related templates and glossary terms
- Templates provide copy-paste SQL and verification steps.
- Glossary terms explain the underlying concepts and failure modes.
How to choose the right conversion from a scan finding
- If a scan says a table is public → start with the “public table → backend-only access” conversion.
- If a scan says a bucket is public/listable → start with the “public bucket → private + signed URLs” conversion.
- If a scan says RPC is publicly executable → start with the “public RPC → service_role-only” conversion.
- If you see multiple findings: prioritize the one that bypasses app auth most easily (often Storage URLs and public reads).
Common conversion pitfalls
- Treating “authenticated” as safe and leaving broad grants in place.
- Fixing dev only and forgetting to apply the same hardening to staging/prod.
- Locking down tables but leaving Storage public (or vice versa).
- Skipping verification and relying on UI behavior.
If you only do one thing
Pick one high-risk exposure, apply one conversion end-to-end, and run verification. One verified win beats five half-finished changes.
If a conversion feels too big
Some conversions are “one SQL change.” Others are “a small architecture shift.” If it feels too big, don’t abandon it — shrink it.
- Pick one resource (one table, one bucket, or one function) and convert only that first.
- Ship the new backend path before you revoke direct access.
- Save the direct access request you used for verification so you can re-run it after migrations.
Security improves fastest when you stack small verified wins instead of attempting a huge refactor all at once.
FAQ
Is a conversion the same as a template?
Not exactly. A conversion is the overall transformation (from unsafe to safe). A template is the concrete implementation guidance and copy‑paste SQL you apply as part of that conversion.
Do conversions require service_role?
Most backend-only patterns do, because privileged access should live in a trusted server environment. The key should never be exposed to the browser.
How do I keep conversions from regressing later?
Add verification steps to your release process (checklist queries, scans after migrations, and monitoring for denied access spikes).
Next step
If you’re not sure which conversion to apply first, run a Mockly scan and start with the highest‑severity exposures.