Supabase
Live audit of your Supabase project — RLS policies, public storage buckets, exposed service-role keys. The findings that matter most for AI-built apps that wired up auth + database in twenty minutes.
Why this matters
Supabase makes it easy to ship auth + database in a single afternoon. That speed is the wedge AI tools amplify — and the edge case the founder hits is always the same: an orders or users table with RLS quietly disabled, or a public storage bucket that any unauthenticated visitor can list. Repo scanning can’t see that. Your Supabase dashboard can. So we read it.
Connect Supabase
Generate a management API token.
From your Supabase dashboard, open Account → Tokens, click Generate new token, name it something like pulselight-readonly, and copy the value (Supabase only shows it once).
Paste into PulseLight.
Project settings → Connected platforms → Supabase → paste the token. We store it KMS-encrypted at rest; the only place it’s ever decrypted is at scan time inside the worker.
Pick the project to audit.
Your token can read every project in your Supabase org. Pick the single project this PulseLight workspace ships against; the others remain invisible to PulseLight.
First scan.
The Supabase Connected Check findings roll into the Secure pillar on the next scan.
What we verify
RLS enabled on user-data tables
We list every public-schema table, then check whether RLS is enabled on tables whose names look like user-data (
users,orders,subscriptions,messages, etc., plus tables your code queries from a per-user route). RLS off → blocker.Storage buckets — public-list policy
For each storage bucket, we check whether the
SELECTpolicy allows unauthenticated listing. Buckets named like uploads (user-uploads,avatars,documents) with public list → blocker.Service-role key in repo
Cross-references your repo (which we already scan) against the project’s service-role key shape. If the secret is in a client-side env var (
NEXT_PUBLIC_*,VITE_*), blocker.Auth provider configured
If your code uses Supabase Auth, we check at least one provider (email, OAuth) is enabled in the Supabase dashboard. Code that calls
signInWithOAuth('google')against an account where Google isn’t configured fails silently in production — we catch it pre-launch.
Common findings
SUPABASE-RLS-001 — RLS disabled on user-data table
Project: my-saas (eu-central-1)
Table: public.subscriptions (12 rows)
Why: Any authenticated user could read any other user's
subscription row. RLS is the only thing standing
between an attacker and a horizontal escalation.
Fix: ALTER TABLE public.subscriptions ENABLE ROW LEVEL
SECURITY; then add a policy keyed on user_id.
SUPABASE-STORAGE-001 — Public-list policy on user-uploads
Bucket: user-uploads
Policy: SELECT allowed to role 'anon'
Files: 142 (sampled)
Why: Any unauthenticated visitor can enumerate filenames
and download. PII / private documents leak.
Fix: Drop the public SELECT policy; require authenticated
reads gated on the file path including the user id.What we don’t do
We never read row data. We don’t inspect query strings or connection logs. We never call mutations of any kind — the token has read-only management scope. The full list of API calls we make is in our Connected Checks overview.
Disconnect
From Settings → Connected platforms → Supabase, click Disconnect. PulseLight purges the token immediately. On the Supabase side, you can revoke it any time from Account → Tokens in your Supabase dashboard.