Skip to content
VibeSafeDaily

LibraryExposed data

The admin client returns every user's rows

Cataloged October 16, 2026 · Lovable · Bolt · Cursor · Supabase

Symptom

The function checks that someone is signed in, then a query through the admin client returns the whole table.

Root cause

Supabase's Edge Function guide says ctx.supabase is scoped to the caller's RLS policies, and ctx.supabaseAdmin bypasses RLS. The danger note on that page: a handler that queries a shared table through ctx.supabaseAdmin without filtering by the caller's id returns every user's rows. Lovable's Deep scan description includes server code that bypasses the rules the database enforces, and privileged actions that only check that the caller signed in.

Fix prompt

In this project's Edge Functions and server routes only:

1. Prefer the RLS-scoped client for anything that serves the signed-in caller.
2. Where an admin client is required, take the user id from the verified JWT (ctx.userClaims or supabase.auth.getUser()), never from the request body, and filter every query with that id.
3. Do not trust a userId, role, or is_admin field sent by the client.
4. Add a test with two users: user B's request must not return user A's rows.

Do not point this change at any other project.

Paste this into the coding tool that has your own project open.

2-minute self-check

These steps are for an app you own. Do not run them against someone else's project.

  1. Search your own functions for supabaseAdmin, service_role, or createClient with the secret key.
  2. For each query, confirm the filter uses the id from the verified session, not from the JSON body.
  3. In your own app, sign in as user B and call the function. The payload should not contain user A's private fields.

Sources

Same symptom