personas
Agency Builder
Delivering multiple client projects on Supabase, you need reusable security baselines that scale across apps without copy-paste mistakes. This page turns the most common risks for this persona into a small set of actions you can apply and verify.
Pain points for a Agency Builder
- Each client app has different constraints but similar exposure patterns
- Template reuse can introduce insecure defaults when rushed
- Hand-offs to client teams often lose critical security context
- You need efficient hardening steps that work across projects
- You need evidence for clients that fixes were validated
Goals for a Agency Builder
- Define a default secure project baseline for new client builds
- Apply standardized templates for tables, storage, and RPC
- Document verification steps clients can run after handoff
- Reduce repeat incidents from the same root causes
What Agency Builders should prioritize first (highest leverage)
- Block direct client access to the most sensitive surface you have today (tables, Storage, or RPC).
- Make verification easy: you should be able to prove the fix with one direct access test.
- Reduce complexity before adding more rules: backend-only access beats a large pile of fragile policies.
- Add one small regression guard (checklist query, scan, or release checklist item).
Recommended templates (fastest safe wins)
- Lock down a public table (backend-only access) β
/templates/access-control/lock-down-public-tableβ A template to revoke direct client access, enable RLS, remove policies, and force all reads/writes through your backend using service_role. - Make a bucket private + serve files with signed URLs β
/templates/storage-safety/make-bucket-private-signed-urlsβ A template to make Supabase Storage buckets private, prevent listing/enumeration, and deliver downloads using short-lived signed URLs from your backend. - Lock down RPC: revoke EXECUTE from public roles β
/templates/rpc-functions/lock-down-rpc-executeβ A template to discover function signatures, revoke EXECUTE from PUBLIC/anon/authenticated, and call RPC only through backend code using service_role. - Remove over-permissive RLS policies (adopt deny-by-default) β
/templates/access-control/remove-over-permissive-policiesβ A template to remove broad policies that leak data and move to a backend-only, deny-by-default posture that is easier to reason about and verify.
Recommended glossary terms (learn the why)
- Row Level Security (RLS) β
/glossary/row-level-securityβ Row Level Security (RLS) is the row-by-row gatekeeper that blocks anon/authenticated clients from touching rows they do not own, but it only protects data when it is enabled and forced. - Public Table Exposure β
/glossary/public-table-exposureβ Public table exposure happens when tables accept anon/authenticated requests without row filters or backend gating, making them effectively open. - Over-permissive RLS Policies β
/glossary/over-permissive-rls-policiesβ Over-permissive RLS policies let too many rows through or cover too many actions, defeating the point of row security. - Supabase Storage Bucket Privacy β
/glossary/supabase-storage-bucket-privacyβ Storage bucket privacy means restricting downloads and listings so only authorized backend code can fetch objects. - RPC EXECUTE Grants β
/glossary/rpc-execute-grantsβ RPC execute grants control which roles can call Postgres functions, and long-lived PUBLIC/anon grants often outlive their intended use. - Signed URLs β
/glossary/signed-urlsβ Signed URLs give temporary, scoped access to private storage objects, but poor signing still leaks data. - Service Role Key β
/glossary/service-role-keyβ The service role key must live on the server; leaking it to the browser hands attackers full database control. - Forced RLS (FORCE ROW LEVEL SECURITY) β
/glossary/force-row-level-securityβ Forcing RLS guarantees ownership filters cannot be bypassed by privileged sessions. - Client Role Grants (anon/authenticated) β
/glossary/client-role-grantsβ Client role grants (anon/authenticated) create an API surface, and misusing them exposes data to any client. - Ownership-bound RLS Policies β
/glossary/ownership-bound-rls-policiesβ Ownership-bound policies tie rows to a user or tenant; missing that link leaves data open. - Storage Object Enumeration β
/glossary/storage-object-enumerationβ Object enumeration happens when buckets allow listing or predictable keys, giving attackers a catalog of files. - Public RPC Surface Area β
/glossary/public-rpc-surface-areaβ Public RPC surface area is every function you leave EXECUTE access to client roles, and it tends to grow into a leak. - NEXT_PUBLIC Secret Leakage β
/glossary/next-public-secret-leakageβ Any secret placed in a NEXT_PUBLIC variable becomes public, so these env vars can never hold sensitive keys. - Broken Object Level Authorization (BOLA) β
/glossary/broken-object-level-authorizationβ Broken Object Level Authorization happens when each object is not validated against the requester, letting attackers read other usersβ data. - Insecure Direct Object References (IDOR) β
/glossary/insecure-direct-object-referencesβ Insecure Direct Object References happen when object IDs are exposed without authorization checks. - Tenant ID Trusted from Client β
/glossary/tenant-id-trust-in-clientβ Trusting tenant IDs from the client lets attackers impersonate other tenants. - Missing WITH CHECK Policy β
/glossary/missing-with-check-policyβ Missing WITH CHECK clauses expose write paths even when reads are locked down. - Broad SELECT for Authenticated Role β
/glossary/broad-authenticated-selectβ Broad authenticated SELECT grants let every logged-in user read sensitive tables. - Broad UPDATE for Authenticated Role β
/glossary/broad-authenticated-updateβ Broad authenticated UPDATE grants let every logged-in user change other peopleβs rows. - Broad DELETE for Authenticated Role β
/glossary/broad-authenticated-deleteβ Broad authenticated DELETE grants allow any logged-in user to remove rows. - Default Privilege Drift β
/glossary/default-privilege-driftβ Default privilege drift happens when inherited grants become permissive, exposing every new object you create. - Schema USAGE Granted to PUBLIC β
/glossary/schema-usage-granted-to-publicβ Granting USAGE on a schema to PUBLIC exposes everything inside it. - Exposed Materialized Views β
/glossary/exposed-materialized-viewsβ Exposed materialized views are cached results that leak data the moment you grant clients access. - Insecure SECURITY DEFINER Functions β
/glossary/insecure-security-definer-functionsβ Insecure SECURITY DEFINER Functions is a Supabase security risk where privileged functions execute with elevated rights but lack strict guardrails, . - Mutable Function search_path β
/glossary/mutable-function-search-pathβ Mutable Function search_path is a Supabase security risk where function execution can be hijacked when search_path is not pinned safely, . - Trigger Privilege Escalation β
/glossary/trigger-privilege-escalationβ Trigger Privilege Escalation is a Supabase security risk where trigger functions perform privileged operations without clear authorization boundaries, . - Migration Owner Bypass of RLS β
/glossary/migration-owner-bypassβ Migration Owner Bypass of RLS is a Supabase security risk where owner-level migration scripts bypass policy assumptions and access controls, . - Shadow Table Without RLS β
/glossary/shadow-table-without-rlsβ Shadow Table Without RLS is a Supabase security risk where new helper tables ship without RLS and silently expose internal data, . - Audit Log Table Publicly Readable β
/glossary/audit-log-public-readableβ Audit Log Table Publicly Readable is a Supabase security risk where diagnostic or audit tables become queryable by client roles, . - Soft Delete Policy Bypass β
/glossary/soft-delete-policy-bypassβ Soft Delete Policy Bypass is a Supabase security risk where deleted rows remain accessible because policies do not enforce deleted-state filtering, . - UPSERT Policy Gap β
/glossary/upsert-policy-gapβ UPSERT Policy Gap is a Supabase security risk where upsert paths bypass intended checks when insert and update logic diverge, . - Cross-Schema Data Exposure β
/glossary/cross-schema-exposureβ Cross-Schema Data Exposure is a Supabase security risk where objects in unintended schemas become reachable through grants or API exposure settings, . - Unrestricted View Definitions β
/glossary/unrestricted-view-definitionsβ Unrestricted View Definitions is a Supabase security risk where views reveal sensitive joins and fields without sufficient access filtering, . - Leaked JWT Signing Secret β
/glossary/leaked-jwt-secretβ Leaked JWT Signing Secret is a Supabase security risk where token-signing secrets leak and allow forged authentication tokens, . - Stale JWT Claims β
/glossary/stale-jwt-claimsβ Stale JWT Claims is a Supabase security risk where authorization decisions rely on outdated claims that no longer match server state, . - Auth Role Claim Confusion β
/glossary/auth-role-claim-confusionβ Auth Role Claim Confusion is a Supabase security risk where role mapping is ambiguous and grants unintended privileges to users, . - Magic Link Open Redirect β
/glossary/magic-link-redirect-open-redirectβ Magic Link Open Redirect is a Supabase security risk where authentication links redirect users to attacker-controlled destinations, . - Password Reset Token Leakage β
/glossary/password-reset-token-leakageβ Password Reset Token Leakage is a Supabase security risk where reset tokens leak through logs, URLs, or client-side handling, . - OAuth Role Mapping Errors β
/glossary/oauth-role-mapping-errorsβ OAuth Role Mapping Errors is a Supabase security risk where external identity attributes are mapped to internal roles without strict checks, . - SSO Group Sync Escalation β
/glossary/sso-group-sync-escalationβ SSO Group Sync Escalation is a Supabase security risk where group sync grants elevated access when role sync rules are too permissive, . - Invite Flow Tenant Escalation β
/glossary/invite-flow-tenant-escalationβ Invite Flow Tenant Escalation is a Supabase security risk where invitation flows allow membership changes beyond intended tenant scope, . - Membership Race Condition β
/glossary/membership-race-conditionβ Membership Race Condition is a Supabase security risk where concurrent membership updates create temporary unauthorized access windows, . - Admin Panel Client-Only Auth β
/glossary/admin-panel-client-auth-onlyβ Admin Panel Client-Only Auth is a Supabase security risk where admin protections live in frontend checks instead of enforceable backend authorization, . - Database URL Leaked in Client β
/glossary/leaked-database-url-in-clientβ Database URL Leaked in Client is a Supabase security risk where database connection details leak into browser bundles and deployment artifacts, . - Secrets in Repository History β
/glossary/secrets-in-repo-historyβ Secrets in Repository History is a Supabase security risk where historical commits expose credentials long after they were removed from current code, . - Environment Parity Security Drift β
/glossary/env-parity-security-driftβ Environment Parity Security Drift is a Supabase security risk where security controls differ across dev, staging, and production environments, . - Staging Database Public Exposure β
/glossary/staging-db-public-exposureβ Staging Database Public Exposure is a Supabase security risk where staging deployments expose production-like data with weak controls, . - Test Data Left in Production β
/glossary/test-data-in-productionβ Test Data Left in Production is a Supabase security risk where non-production data handling introduces privacy and integrity risks, . - Unencrypted Sensitive Columns β
/glossary/unencrypted-sensitive-columnsβ Unencrypted Sensitive Columns is a Supabase security risk where high-risk fields are stored without column-level encryption or tokenization strategy, . - Missing Key Rotation Policy β
/glossary/key-rotation-policy-missingβ Missing Key Rotation Policy is a Supabase security risk where long-lived secrets persist without rotation, increasing blast radius during incidents, . - Service Role Overreach in Cron Jobs β
/glossary/service-role-overreach-in-cronβ Service Role Overreach in Cron Jobs is a Supabase security risk where scheduled jobs run with excessive privileges for routine operations, . - PII in Error Traces β
/glossary/pii-in-error-tracesβ PII in Error Traces is a Supabase security risk where stack traces and error payloads leak personal data across observability systems, . - PII in Analytics Events β
/glossary/pii-in-analytics-eventsβ PII in Analytics Events is a Supabase security risk where tracking events include sensitive fields not needed for product analytics, . - Missing Data Retention Policy β
/glossary/data-retention-policy-missingβ Missing Data Retention Policy is a Supabase security risk where sensitive data is kept indefinitely without lifecycle controls, . - Incomplete GDPR Delete Flow β
/glossary/incomplete-gdpr-delete-flowβ Incomplete GDPR Delete Flow is a Supabase security risk where delete flows remove top-level records but leave recoverable personal data behind, . - No Exfiltration Anomaly Detection β
/glossary/no-anomaly-detection-exfiltrationβ No Exfiltration Anomaly Detection is a Supabase security risk where large abnormal data reads go unnoticed without baseline monitoring and alerting, . - Weak Tenant Isolation Tests β
/glossary/weak-tenant-isolation-testsβ Weak Tenant Isolation Tests is a Supabase security risk where automated tests fail to prove cross-tenant access is consistently blocked, . - Policy Drift After Schema Rename β
/glossary/policy-drift-after-schema-renameβ Policy Drift After Schema Rename is a Supabase security risk where renamed tables and columns silently desynchronize policy behavior, . - Orphaned Policies After Table Rename β
/glossary/orphaned-policies-after-table-renameβ Orphaned Policies After Table Rename is a Supabase security risk where legacy policies remain detached from intended objects after refactors, . - Generated Columns Leak Sensitive Data β
/glossary/generated-columns-sensitive-leakβ Generated Columns Leak Sensitive Data is a Supabase security risk where derived columns unintentionally expose sensitive source attributes, . - View Without Security Barrier β
/glossary/view-without-security-barrierβ View Without Security Barrier is a Supabase security risk where view planning behavior can leak data when security barriers are not applied, . - Missing Column-Level Redaction β
/glossary/column-level-redaction-missingβ Missing Column-Level Redaction is a Supabase security risk where applications expose full records when only partial fields should be visible, . - Unrestricted PostgREST Origin Proxy β
/glossary/unrestricted-postgrest-originβ Unrestricted PostgREST Origin Proxy is a Supabase security risk where proxy layers forward API requests without validating trusted origins, . - CORS Misconfiguration in Edge Functions β
/glossary/cors-misconfiguration-edge-functionsβ CORS Misconfiguration in Edge Functions is a Supabase security risk where permissive CORS allows untrusted origins to trigger privileged flows, . - Missing Webhook Signature Validation β
/glossary/missing-webhook-signature-validationβ Missing Webhook Signature Validation is a Supabase security risk where incoming webhooks are trusted without cryptographic authenticity checks, . - Webhook Replay Attack Risk β
/glossary/webhook-replay-attack-riskβ Webhook Replay Attack Risk is a Supabase security risk where valid webhook messages can be replayed to repeat sensitive actions, . - Billing Webhook Idempotency Gap β
/glossary/billing-webhook-idempotency-gapβ Billing Webhook Idempotency Gap is a Supabase security risk where billing events are processed multiple times and create inconsistent account states, . - Insecure Edge Function Authentication β
/glossary/insecure-edge-function-authβ Insecure Edge Function Authentication is a Supabase security risk where edge endpoints process privileged actions before enforcing robust auth checks, . - Edge Function Service Role Overuse β
/glossary/edge-function-service-role-overuseβ Edge Function Service Role Overuse is a Supabase security risk where service role credentials are used in functions that only need limited permissions, . - RPC Dynamic SQL Injection β
/glossary/rpc-dynamic-sql-injectionβ RPC Dynamic SQL Injection is a Supabase security risk where function logic builds SQL dynamically from untrusted parameters, . - RPC Missing Input Validation β
/glossary/rpc-missing-input-validationβ RPC Missing Input Validation is a Supabase security risk where RPC handlers accept malformed or dangerous inputs without strict validation, . - RPC Unbounded Result Sets β
/glossary/rpc-unbounded-result-setβ RPC Unbounded Result Sets is a Supabase security risk where RPC functions return excessive rows and enable low-cost data scraping, . - RPC Error Message Data Leak β
/glossary/rpc-error-data-leakβ RPC Error Message Data Leak is a Supabase security risk where error paths disclose stack details, SQL fragments, or sensitive identifiers, . - Public Function Source Disclosure β
/glossary/public-function-source-disclosureβ Public Function Source Disclosure is a Supabase security risk where function definitions leak business logic and internal assumptions to low-privilege roles, . - Overloaded RPC Signature Miss β
/glossary/overloaded-rpc-signature-missβ Overloaded RPC Signature Miss is a Supabase security risk where security reviews miss overloaded signatures that remain callable with weaker controls, . - Unrestricted Admin Search Endpoint β
/glossary/unrestricted-admin-search-endpointβ Unrestricted Admin Search Endpoint is a Supabase security risk where search endpoints provide broad access to internal records and metadata, . - Bulk Export Endpoint Overexposure β
/glossary/bulk-export-endpoint-overexposureβ Bulk Export Endpoint Overexposure is a Supabase security risk where export APIs allow high-volume extraction without strong authorization and limits, . - CSV Import Trusts Client Columns β
/glossary/csv-import-trusts-client-columnsβ CSV Import Trusts Client Columns is a Supabase security risk where import flows allow users to overwrite sensitive fields through crafted headers, . - Row Ownership Transfer Without Recheck β
/glossary/row-ownership-transfer-without-recheckβ Row Ownership Transfer Without Recheck is a Supabase security risk where ownership updates are accepted without validating transfer authority, . - File Upload MIME Spoofing β
/glossary/file-upload-mime-spoofingβ File Upload MIME Spoofing is a Supabase security risk where uploaded files bypass validation by spoofing content type metadata, . - Storage Upload Size Abuse β
/glossary/storage-upload-size-abuseβ Storage Upload Size Abuse is a Supabase security risk where uploads lack size limits and create denial-of-wallet and abuse risks, . - Missing Malware Scanning on Uploads β
/glossary/missing-malware-scanning-uploadsβ Missing Malware Scanning on Uploads is a Supabase security risk where user-uploaded files are served without malware scanning or quarantine workflows, . - Public Backup Bucket Leak β
/glossary/public-backup-bucket-leakβ Public Backup Bucket Leak is a Supabase security risk where backup artifacts become publicly readable through misconfigured storage buckets, . - Expired Signed URL Caching Leak β
/glossary/expired-signed-url-caching-leakβ Expired Signed URL Caching Leak is a Supabase security risk where cached responses keep files accessible after signed URL expiry windows, . - Object Path Predictability Risk β
/glossary/object-path-predictability-riskβ Object Path Predictability Risk is a Supabase security risk where predictable object paths make private assets easy to enumerate and scrape, . - Storage Lifecycle Policy Missing β
/glossary/storage-lifecycle-policy-missingβ Storage Lifecycle Policy Missing is a Supabase security risk where old objects remain accessible because storage lifecycle and cleanup policies are absent, . - Bucket LIST Permission Too Broad β
/glossary/bucket-list-permission-too-broadβ Bucket LIST Permission Too Broad is a Supabase security risk where list permissions expose object inventories that assist targeted abuse, . - Realtime Channel Authorization Gap β
/glossary/realtime-channel-authorization-gapβ Realtime Channel Authorization Gap is a Supabase security risk where channel subscriptions are accepted without enforcing tenant-aware authorization rules, . - Realtime Presence Data Leak β
/glossary/realtime-presence-data-leakβ Realtime Presence Data Leak is a Supabase security risk where presence metadata reveals user behavior and identifiers to unauthorized clients, . - Publication Includes Sensitive Tables β
/glossary/publication-includes-sensitive-tablesβ Publication Includes Sensitive Tables is a Supabase security risk where logical replication publishes sensitive tables that should never stream to clients, . - Replication Role Overgrant β
/glossary/replication-role-overgrantβ Replication Role Overgrant is a Supabase security risk where replication roles receive privileges beyond strict replication requirements, . - Unbounded Pagination Enumeration β
/glossary/unbounded-pagination-enumerationβ Unbounded Pagination Enumeration is a Supabase security risk where pagination controls are weak and allow low-cost full dataset traversal, . - Guessable Primary Keys β
/glossary/guessable-primary-keysβ Guessable Primary Keys is a Supabase security risk where sequential or predictable identifiers simplify unauthorized record discovery, . - Missing Rate Limits on Write Paths β
/glossary/rate-limit-missing-on-write-pathsβ Missing Rate Limits on Write Paths is a Supabase security risk where write endpoints can be abused for spam, brute force, and denial-of-wallet, . - Missing CAPTCHA on Sensitive Flows β
/glossary/missing-captcha-sensitive-flowsβ Missing CAPTCHA on Sensitive Flows is a Supabase security risk where high-risk workflows lack anti-automation controls against scripted abuse, . - Insecure Feature Flag Disclosure β
/glossary/insecure-feature-flag-disclosureβ Insecure Feature Flag Disclosure is a Supabase security risk where flag payloads expose hidden capabilities and internal rollout logic, . - No Two-Person Review for Privilege Changes β
/glossary/no-two-person-review-privilege-changesβ No Two-Person Review for Privilege Changes is a Supabase security risk where single-actor privilege changes increase risk of accidental or malicious escalation, . - Dependency Drift Misses Security Updates β
/glossary/dependency-drift-security-updates-missedβ Dependency Drift Misses Security Updates is a Supabase security risk where stale dependencies keep known vulnerabilities in critical runtime paths, . - Private Key Material in Logs β
/glossary/private-key-material-in-logsβ Private Key Material in Logs is a Supabase security risk where sensitive key material is accidentally emitted to application and infrastructure logs, . - API Cache Leaks Private Data β
/glossary/api-cache-private-data-leakβ API Cache Leaks Private Data is a Supabase security risk where shared caches return user-specific responses to unauthorized sessions, . - Data API Public Schema Exposure β
/glossary/data-api-public-schema-exposureβ Data API Public Schema Exposure occurs when sensitive tables remain in exposed schemas, making direct REST or GraphQL access possible with client-side credentials. - Data API Custom Schema Misconfiguration β
/glossary/data-api-custom-schema-misconfigurationβ Data API Custom Schema Misconfiguration happens when teams move to a custom exposed schema but leave permissive grants, search paths, or legacy objects that keep data reachable. - pg_graphql Extension Exposure β
/glossary/pg-graphql-extension-exposureβ pg_graphql Extension Exposure appears when GraphQL remains enabled on schemas or objects that should not be reachable from client credentials. - Realtime Public Channel Mode β
/glossary/realtime-public-channel-modeβ Realtime Public Channel Mode is the risk of allowing broad channel subscription without private-channel authorization rules and topic scoping. - Realtime Topic Policy Mismatch β
/glossary/realtime-topic-policy-mismatchβ Realtime Topic Policy Mismatch occurs when channel topic patterns and RLS authorization logic diverge, allowing unintended subscribers or publishers. - Realtime Broadcast Overexposure β
/glossary/realtime-broadcast-overexposureβ Realtime Broadcast Overexposure is the accidental publication of sensitive payloads to channels where recipients are broader than intended. - Edge Function JWT Verification Gap β
/glossary/edge-function-jwt-verification-gapβ Edge Function JWT Verification Gap occurs when function handlers skip or misapply token validation, allowing unauthorized execution paths. - Service Role Authorization Header Override β
/glossary/service-role-authorization-header-overrideβ Service Role Authorization Header Override is when a client initialized for admin use silently runs with user session headers, changing expected privilege behavior. - Publishable vs Secret Key Scope Confusion β
/glossary/publishable-secret-key-scope-confusionβ Publishable vs Secret Key Scope Confusion is the misuse of key types across client and server boundaries, resulting in over-privileged execution paths. - Missing Network Restrictions β
/glossary/missing-network-restrictionsβ Missing Network Restrictions means database and pooler endpoints are reachable from unrestricted IP ranges, increasing brute-force and credential abuse risk. - IPv6 Allowlist Gap β
/glossary/ipv6-allowlist-gapβ IPv6 Allowlist Gap is the mistaken assumption that IPv4 restrictions are enough, leaving IPv6 connection routes less constrained than intended. - Default Function EXECUTE to PUBLIC β
/glossary/default-function-execute-to-publicβ Default Function EXECUTE to PUBLIC is the risk that newly created routines remain callable by broad roles unless explicit revokes/default privileges are applied. - Untrusted Language Function Risk β
/glossary/untrusted-language-function-riskβ Untrusted Language Function Risk is the danger of running routines with capabilities that can circumvent normal access boundaries if creation/execution controls are weak. - Storage Authenticated Endpoint Overtrust β
/glossary/storage-authenticated-endpoint-overtrustβ Storage Authenticated Endpoint Overtrust is relying on logged-in status alone for private file access without strict path ownership and bucket policy checks.
A safe default architecture for Agency Builders
If youβre not sure which model to choose, this default posture prevents many Supabase leaks:
- The browser is untrusted and uses only anon/auth tokens for public, non-sensitive actions.
- All sensitive reads/writes go through backend endpoints (server actions or API routes).
- Service-role secrets never leave the server environment.
- RLS is used as a safety gate, not the only authorization mechanism.
You can always relax this posture later if you intentionally want client-side access β but tightening after a leak is harder.
A simple weekly security rhythm
- Scan or run checklist queries after schema changes.
- Fix one high-risk exposure (tables, storage, RPC).
- Verify via direct client access tests.
- Document the decision and add a regression check.
Verification loop for a Agency Builder (what βdoneβ looks like)
- You can reproduce the risky behavior before the fix (so youβre not guessing).
- After the fix, the same direct access attempt fails with a clear denial.
- The app still works through backend endpoints for authorized users.
- A scan/checklist re-run confirms the exposure signal is gone.
- You wrote down the rule so the next schema change doesnβt reintroduce it.
Common traps (what to avoid)
- Shipping quick policy changes without verification.
- Leaving Storage public because itβs βonly filesβ.
- Keeping RPC callable because itβs βjust internalβ.
- Putting service_role in client env vars.
What to automate next (as Agency Builders mature)
- A drift check after migrations: new tables with RLS disabled, new public EXECUTE grants, new public buckets.
- A lightweight βsecurity changeβ checklist in PRs: policies, grants, buckets, functions, auth flows.
- Monitoring for unusual reads/writes, especially anonymous access to sensitive surfaces.
A one-day hardening plan for a Agency Builder
- Pick one surface (tables, Storage, or RPC) and inventory the resources you consider sensitive.
- Apply one template/conversion end-to-end and keep the change small.
- Run verification (direct access fails) and fix any missed app call paths.
- Document the access model and add a drift guard for the next migration.
- Repeat for the next surface next week instead of trying to do everything at once.
What to monitor as a Agency Builder
- Unexpected anonymous reads/writes or Storage downloads.
- Denied access spikes after tightening permissions (often indicates missed app paths).
- Changes to policies/grants/buckets/functions that didnβt go through review.
Common scenarios for a Agency Builder (and the safest response)
- A new table ships and the UI needs data quickly β add a backend endpoint first, then decide if client access is truly necessary.
- A file download feature ships fast β keep buckets private and use signed URLs from the server, even if it feels slower at first.
- A new function is added for convenience β treat RPC as privileged by default and revoke public EXECUTE unless reviewed.
- A migration changes policies/grants β re-run verification checks immediately to catch drift before users do.
A βboundary statementβ template for Agency Builders
A boundary statement is a one-sentence rule you can put in docs and PRs so security is reviewable and testable.
Use this template and fill it in:
- Only the backend can (operation) on (resource) because (reason).
- The browser can only (safe operation) and must never call (privileged path) directly.
- Verification: the direct access test (describe it) must fail in dev/staging/prod.
Writing this down turns security into a repeatable habit and makes regressions obvious.
FAQ
Whatβs the single most effective fix for a Agency Builder?
Backend-only access for sensitive operations. It reduces exposure and makes future changes safer, regardless of how complex your schema becomes.
How do I prioritize what to fix first?
Start with anything publicly accessible: exposed tables, public/listable Storage, and public RPC. Then harden permissive policies and drift.
How do I know Iβm done?
Youβre never βdone,β but you can be in a stable posture: direct client access fails for sensitive resources, backend endpoints enforce auth, and scans/checklists run after every migration.
Next step
Want this advice tied to your exact exposures? Run a Mockly scan and follow the recommended templates from your findings.
Explore related pages
cross
Make a bucket private + serve files with signed URLs/templates/storage-safety/make-bucket-private-signed-urls