Skip to content

GUIDE 05 · WEB APPLICATIONS AND APIs

Supabase security: check RLS and access to data

Supabase row-level security must enforce the permissions of actual application users, not just succeed in an administrative SQL session. Test two independent users and known rows, including permitted reads, forbidden cross-owner access and attempts to change ownership. Keep privileged keys on trusted servers.

Scantelio editorial team · Updated

Check your Supabase application

Sign-in, ownership verification and consent are required. Authorized scenarios, monitoring and CI require Pro or Business.

On this page

Understand browser-to-data access

A browser can call the data API directly when the application is configured that way. The access boundary must therefore hold at the database and API layers. Hiding a UI action does not protect a row. Confirm which role and authenticated identity reach the database for each request.

Separate public and privileged keys

A publishable or anon key is intended for public-client use under appropriate grants and RLS. A secret or service_role key belongs on a trusted server and may bypass RLS. Do not use a privileged context as evidence that a user-level policy works; test the actual authenticated client identity.

KeyIntended locationBoundary
publishable / anonPublic client with correct RLSNot a permission to bypass policy
secret / service_roleTrusted server onlyMay bypass RLS; never in a browser bundle
User JWTAuthenticated user requestVerify token and permissions; do not publish

Primary sources: Primary reference 1 · Primary reference 2

Continue: IDOR and BOLA: test access to another user’s data

Describe the rules of your table

For each action, specify the row owner or organization, caller role and permitted fields. Enable RLS and review grants. A read policy does not automatically authorize a safe write. Shared data requires its own explicit policy rather than assumptions based on the owner-only example.

A minimal owner-read policy

The example below restricts SELECT to the authenticated owner. Replace its table and column names with your own schema, and keep other actions separate. The downloadable local fixture uses PostgreSQL with a clearly named test identity function; it is not a claim that an actual hosted Supabase project was exercised.

Supabase owner-read policy; the downloaded local PostgreSQL fixture uses an explicit test identity function.
alter table public.documents enable row level security;
create policy "owner reads" on public.documents
for select to authenticated
using (owner_id = (select auth.uid()));

Primary sources: Primary reference 1 · Primary reference 2

Continue: Exposed .env, .git or API keys: contain the leak and verify the fix

Check your Supabase application

Check inserts and ownership changes

WITH CHECK validates the proposed new row, while USING selects the rows an operation may act on. Verify that A cannot insert a row owned by B or transfer its own row to B without permission. Also verify a permitted edit so an unusable table is not mistaken for a secure application.

Use a two-user matrix

Check owner reads, cross-owner reads, anonymous access, foreign-owner inserts and ownership changes. A denied SELECT may return an empty array rather than a 403. The local SQL fixture runs seven assertions as an ordinary non-login role and rolls back its objects; cloud validation remains a separate acceptance step.

Local SQL scenarioExpected outcome
A reads AOne visible row
A reads BNo visible rows
B reads BOne visible row
Anonymous readNo private rows
A inserts owner BWITH CHECK denies
A changes owner to BWITH CHECK denies
After the local testTransaction rolled back

Primary sources: Primary reference 1 · Primary reference 2

Continue: Next.js security: check APIs, Server Actions and secrets

Inspect adjacent access paths

Review storage buckets, views, RPC functions and backend services that use privileged keys. Their behavior is not proven by a policy on one table. Evaluate each exposed path under the identities that really use it. Scantelio’s configured HTTP scenarios complement, rather than replace, a database policy review.

Apply the change and repeat

Version the schema and policy change, deploy it to a test environment and repeat both denials and positive controls. Then follow your normal reviewed release process. Preserve the tested schema, identities, sanitized outcomes and deployment revision; never include working user tokens in the evidence.

Continue: Prepare an automated API security assessment

Reproducible examples and downloads

Tested with: guides-1 · PostgreSQL RLS — local fixture

All example data is synthetic. Downloads contain no active keys or customer records. Run examples only in your own isolated test environment.

Example verification record: versions, actions and observations

Actual Scantelio evidence panel displaying the controlled fixture result; this is not a customer scan or a full end-to-end scan
Actual Scantelio evidence panel displaying the controlled fixture result; this is not a customer scan or a full end-to-end scan. Test fixture, synthetic data.

Questions and answers

Is the anon key a secret?

It is designed for public-client use with correct permissions. Privileged secret/service-role keys are different.

Does enabling RLS solve every access issue?

No. Policies, grants, functions, storage and privileged server paths still need review.

Why does a denied read return 200?

Row filtering may legitimately produce a successful response with an empty result set.

Can I test through SQL Editor alone?

That does not reproduce the actual user context. Use authenticated client requests as well.

Was the example tested in hosted Supabase?

The supplied automated example was tested in local PostgreSQL. The protocol states that limitation explicitly.

Can Scantelio infer the intended policy?

No. Provide identities, known objects and expected permissions for supported HTTP access checks.

Editorial team and sources

Scantelio editorial team: methodology and limitations. Example verified: 2026-11-02.

Apply the check to your own project

Check your Supabase application

Choose your project after signing in. No scan runs without verification and consent.