Supabase RLS: the 5 mistakes we find in every HR SaaS audit
The false sense of security
Supabase has become the default choice for many French HR startups. And for good reason: managed PostgreSQL, built-in auth, auto-generated API. You can ship an MVP in weeks.
The problem is that this speed creates a false sense of security. "We enabled RLS, so we're secure." No. Enabling RLS is putting a lock on the door. But if the policy allows everyone in, the lock does nothing.
Here are the 5 mistakes we find systematically.
Mistake 1: overly permissive SELECT policy
The most common policy we see:
```sql
CREATE POLICY "Users can read" ON employees
FOR SELECT USING (true);
`
Every authenticated user can read every employee. In a multi-tenant SaaS, company A can see company B's employees.
The fix:
```sql
CREATE POLICY "Users can read own org" ON employees
FOR SELECT USING (org_id = auth.jwt() ->> 'org_id');
`
Mistake 2: forgetting policies on related tables
You've secured the employees table, but not payslips. An attacker can list all payslips by querying the payslips table directly, even without access to the employees table.
Every table with sensitive data needs its own policies. And joins must be verified: if payslips has an employee_id column, the policy must check that the employee belongs to the current user's organization.
Mistake 3: service_role key in the frontend
We still see this regularly: the Supabase service_role key hardcoded in frontend JavaScript. This key bypasses all RLS policies. Anyone inspecting the source code can extract it and access the entire database.
The service_role key must never leave your server. The frontend uses the anon key — that's what RLS policies are for.
Mistake 4: no policies on INSERT and UPDATE
Many teams add policies on SELECT but forget INSERT and UPDATE. Result: an authenticated user can create an employee in any organization, or modify someone else's salary.
Every operation (SELECT, INSERT, UPDATE, DELETE) needs its own policy. And UPDATE policies must check both existing rows (USING) and new values (WITH CHECK).
Mistake 5: unsecured RPC functions
Supabase lets you create PostgreSQL functions exposed via API (RPC). These often run with the creator's permissions (SECURITY DEFINER), which bypasses RLS.
If your RPC function does SELECT * FROM employees WHERE id = $1 without checking the organization, a user can access any employee by passing the ID directly.
Solution: use SECURITY INVOKER when possible, or add organization checks within the function itself.
Bonus mistake: Storage buckets without policies
RLS policies on your tables do not protect Supabase Storage. Buckets have their own, separate policies, and we regularly find payslips, contracts and ID documents in buckets readable by any authenticated user — or even public.
Check every bucket: is it marked public? Which policies control upload, download and deletion? An HR document should only be readable by its owner and authorized roles within the same organization.
How to verify your policies hold
The simplest test: create two user accounts in two different organizations. Log in as user A and try to access B's data. Not just through the UI — directly via the Supabase API with curl or Postman.
That's exactly what we do in a Supabase audit at CleanIssue. We test every table, every RPC endpoint, every storage bucket. And we document precisely what leaks and how to fix it.
Building HR, payroll, or recruiting software? CleanIssue performs security audits for HR SaaS in real-world conditions, no source code access needed. For a first read of your exposure, start with an external review of your application.
Related articles
Three adjacent analyses to keep exploring the same attack surface.
RLS mistakes: the 2026 guide for Supabase, PostgreSQL, and multi-tenant access control
The most expensive RLS mistakes in Supabase and PostgreSQL: incomplete policies, overpowered roles, fragile JWT assumptions, exposed service_role keys, and false confidence.
Supabase and HR software: configuration mistakes that expose payslips
The Supabase mistakes that matter in HR or payroll software: incomplete RLS policies, overly open buckets, and weak organization boundaries.
SPF, DKIM, DMARC: protecting your payroll emails from spoofing
A fake payslip email sent from your domain, and your reputation is gone. A practical SPF, DKIM and DMARC guide for HR SaaS vendors, with the most common configuration mistakes.
Sources
Related services
If this topic maps to a real risk in your stack, these are the most relevant CleanIssue audits.