Supabase RLS Explained | Review Row-Level Access and Data Exposure
Quick answer: With RLS disabled, table privileges determine access. With RLS enabled and no applicable policies, roles subject to RLS are denied access. Permissive policies can expose rows. Roles with BYPASSRLS, such as service_role, ignore RLS policies.
By Paula C · Kraftwire Software
· 8 min readSupabase access control combines database privileges, RLS policies, and request roles. Review generated migrations and deployed settings whether you use Lovable, Bolt.new, Cursor, or write the code manually.
These live figures describe all scanned sites. They do not establish prevalence for an AI-built subgroup, compare development methods, or attribute findings to AI generation.
30% of the 119 live sites SimplyScan has scanned (36 sites) have at least one high or critical security issue.
Review table privileges, row policies, and privileged access together when assessing data exposure.
Why Is Missing Row Level Security Dangerous?
A Supabase frontend can use the Data API with an anon key, which is designed for public client configuration. Possession of the anon key is not individual user authentication; requests from signed-in users can carry their user access token.
With RLS disabled, table privileges determine access. Enabled RLS without applicable policies denies row access for subject roles; permissive policies can expose rows. Superusers and BYPASSRLS roles bypass RLS, and table owners normally bypass it unless forced to obey it. Inspect the actual request role: an unauthenticated anon request and an authenticated user request can have different access.
How Does Supabase RLS Work?
Row-Level Security is a PostgreSQL feature that restricts rows for applicable read and write operations. Policies work alongside table privileges; they do not replace all database or application access controls.
For example, a typical policy might state: "A user can only see rows in the profiles table where the id column matches their own auth.uid()."
For Data API requests, verified authentication context determines the database role and claims available to policy expressions. RLS evaluates applicable policies; the database does not interpret arbitrary browser identity values as trusted. Review privileges and bypass paths separately.
Table Privileges and Row Policies
An application query such as SELECT * FROM posts WHERE user_id = 123 illustrates explicit filtering; the identity must come from trusted authentication. With SELECT * FROM posts, applicable RLS policies can restrict returned rows even without an application filter. Policy evaluation is more than literally appending a WHERE string.
What Happens If I Forget To Enable RLS?
Without RLS, a granted role may read or modify rows according to its table privileges. Determine whether that access is intended; disabled RLS alone does not establish public exposure.
13% of the 119 live sites SimplyScan has scanned (15 sites) have at least one high-severity web-security issue, such as a missing Content-Security-Policy or HSTS header.
7% of the 119 live sites SimplyScan has scanned (8 sites) have at least one high-severity possible Supabase access-control issue, such as a table that may lack Row Level Security.
When reviewing database access:
- Check the table privileges granted to each request role.
- Check whether RLS is enabled and which policies apply.
- Test permitted and denied operations, including access through privileged bypass roles.
Inspect migrations and deployed settings. ALTER TABLE "table_name" ENABLE ROW LEVEL SECURITY; enables RLS on the named table, but review grants and operation-specific policies as well.
How Do I Check For Missing RLS Policies?
Checking for missing RLS is a multi-step process. You cannot simply check if RLS is "on"; you must also check if the policies actually do what you think they do.
1. Inspect the Deployed Table
Review RLS status, table grants, and policies in the current Supabase dashboard or system catalogs. Test the permissions of the actual anon and signed-in request roles; a warning badge alone is not a complete assessment.
2. Investigate Public Observations
SimplyScan’s URL scanner performs supported anonymous backend probes. It does not inspect every table’s RLS state or test every authenticated user. A successful fetch of data requires investigation of whether that data was intended to be public.
3. Query PostgreSQL Catalogs
This query lists ordinary tables in the public schema with RLS disabled. It does not cover every schema, partitioned parent, view, or effective permission:
Which rls misconfigurations should I check?
Review the Supabase checklist alongside the actual grants, policies, and request roles.
A Permissive Read Policy
A policy condition of true allows matching rows for its covered operation and roles, subject to table privileges and other applicable policy rules:
This SELECT policy is suitable only where its effective access is intended. Other applicable restrictive policies can further limit access.
Service-Role Exposure
A credential used as the service_role database role bypasses RLS, subject to that role’s privileges. Keep it in a trusted backend and authorize callers before using it. If it reaches client code or a publicly served .env file, revoke it and investigate access. See architecture risks.
Operation Coverage
Test SELECT, INSERT, UPDATE, and DELETE separately with the relevant grants and roles. Missing applicable policies deny the affected row operation for subject roles. For UPDATE, review the existing-row condition and the new-row check; if WITH CHECK is omitted, PostgreSQL can reuse USING where that policy permits both.
How Can I Secure My Supabase App Quickly?
Plan and test grants and policies for the intended access model before changing production. If exposure is suspected, contain it and investigate affected access.
Enable RLS for Exposed Tables
For a table exposed through the Data API, use ALTER TABLE "table_name" ENABLE ROW LEVEL SECURITY; with the correct table name. Review other exposed schemas as well as public, and test the migration’s effect.
Review Default Denial
Without applicable policies, roles subject to RLS cannot access rows. Privileged bypass roles and normally table owners are exceptions; enabling RLS can also interrupt legitimate application access.
Add Specific Policies
Use policies for the intended roles and operations. An ownership condition such as auth.uid() = user_id needs the correct schema, trusted identity, and read/write checks; test allowed and denied cases.
Audit Credentials
Keep the service_role credential server-side and review anon access separately. Use SimplyScan for supported public secret-exposure observations, alongside code and configuration review.
Understand Badge Limits
A verified security badge links to a dated scan’s score and eligibility state, subject to the badge criteria. It does not prove the absence of vulnerabilities.
Is Vibe Coding Inherently Less Secure?
AI-generated migrations and policies require independent review and tests. The generation method does not establish correct permissions.
The average security score across the 119 live sites SimplyScan has scanned is 86 out of 100.
This average describes all scanned sites, not AI-tool policy quality. Review deployed settings and test permissions for Bolt.new or Lovable projects.
Review generated code and deployed configuration directly, and test application-specific behavior alongside the supported automated checks.
79% of the 119 live sites SimplyScan has scanned (94 sites) have at least one medium-severity speed issue, such as render-blocking scripts or no route-based code splitting.
Investigate performance observations separately from access-control findings. A speed result does not establish whether a database policy is correct.
How Does SimplyScan Help With Supabase Security?
SimplyScan uses supported public content and anonymous backend responses. It does not inspect all private configuration or reproduce every authenticated user interaction.
The free SimplyScan URL scan checks supported secret patterns, security headers, and anonymous backend exposure. A public project key is not automatically a secret. Investigate findings and test private policies, authenticated access, XSS defenses, and CSRF defenses separately.
Pro Monitoring includes Pro scan credits for full reports. See pricing for the allowance associated with your chosen option.
Pro Monitoring provides scheduled rescans with change alerts, uptime monitoring, and supported Slack/GitHub integrations. A rescan may reveal supported exposure, but it does not inspect every new table or prevent regressions.
Use database-review guidance, supported findings, and direct tests together. Record the roles and operations actually covered.
Supabase Access-Control Review
- Review RLS and grants for tables exposed through the API, including the
publicschema. - Use trusted identity helpers such as
auth.uid()in appropriate policy expressions. - Keep
service_rolecredentials out of client code. - Test unauthenticated and authenticated allowed/denied operations.
- Investigate supported SimplyScan findings and remaining coverage gaps.
By following these steps, you can reduce access-control risks and check the resulting configuration. Verify RLS configuration alongside authentication, table privileges, and privileged server-side access.
Frequently asked questions
What is Supabase RLS and why do I need it?
RLS restricts row access for applicable PostgreSQL roles and operations. Table privileges still apply. Disabled RLS leaves row access to other controls; enabled RLS without applicable policies denies rows to subject roles. Superusers and BYPASSRLS roles bypass it, and table owners normally bypass it unless forced to obey it.
How do I check if my Supabase tables are missing RLS?
Inspect deployed RLS status, grants, and policies in the dashboard or PostgreSQL catalogs, then test actual request roles. SimplyScan provides supported anonymous backend observations; it does not list every table’s RLS state or verify all authenticated access.
Is the Supabase anon key safe to use in my frontend?
The anon key is intended for public client configuration. Review the effective permissions of unauthenticated and signed-in requests, including grants, policies, and server-side behavior. The key’s visibility alone is not a leak, and enabling RLS alone does not prove the entire application is safe.
What is the difference between the anon key and service_role key?
A request using the service_role database role can bypass RLS, subject to its database privileges. Keep that credential in a trusted backend and authorize callers before using it. Public anon credentials do not grant the same bypass privileges.
How do I enable RLS on an existing Supabase table?
Enable RLS on the intended table with ALTER TABLE, then configure grants and policies for the intended roles and operations. Test permitted and denied reads and writes before deploying the change. Without applicable policies, subject roles are denied row access; privileged bypass paths remain separate.
Which supabase rls misconfigurations to avoid should I check?
Review permissive policies, grants, request roles, bypass paths, and leaked service-role credentials. Test reads and writes with separate users. Missing applicable policies deny the affected operations for subject roles; they do not grant access to everyone.