Precursor Security
Intelligence Library
Guide

Row-Level Recklessness: A Guide to Supabase Security Testing

17 June 2025
·
15 min read
·Precursor Security

Supabase is an open-source Firebase alternative built on PostgreSQL with a PostgREST API layer. Its ease of setup conceals configuration depth that frequently introduces serious security vulnerabilities. The highest-value areas for Supabase security testing are authentication quirks, row-level security (RLS) misconfiguration, and exposed frontend logic.

What Are the Key Supabase Security Testing Areas?

  • Supabase is an open-source Firebase alternative built on Postgres with a RESTful API layer.
  • It's easy to set up but has configuration depth that can introduce serious security issues.
  • Key areas to test: authentication quirks, row level security (RLS), and exposed frontend logic.
  • Supabase's Security Advisor tool can help validate findings.

What is Supabase?

If you've been anywhere near technology since the advent of large language models, you have likely heard Supabase mentioned. Often, this is currently marred with the brush of "Vibe Coding", which rightfully has some critics. However, I would argue that Supabase's popularity in this space comes from its ease to set up and get going, and its scalability if your app is successful. Add in that Supabase is open source so should be here for the future, and I think it is quite a good choice to back your application for most people. In this article, we will be focusing on the hosted version of Supabase at https://supabase.com, not on the self-hosted offering.

Supabase is billed as an open source competitor to Google's offering Firebase. With more than 1.7 million registered developers on its platform (as of March 2026, per supabase.com/company), it has grown into a serious production choice for early-stage and growth-stage teams alike. It provides a complete backend stack, using PostgreSQL as the database and PostgREST middleware for API queries. It includes built-in authentication, Open Authorization (OAuth), authorisation, and logging.

What the hell is PostgREST?

You heard right, Supabase uses a piece of technology called PostgREST, a portmanteau of Postgres and REST. PostgREST builds a fully RESTful API from an existing PostgreSQL database without any configuration needed. Each DB table becomes an API endpoint which can be refined with query parameters. It is an elegant solution when tied with Row Level Security (RLS), which allows the developer to specify which users can access or modify which pieces of data, which acts as the authorisation layer.

How Do You Test a Supabase Application for Security Issues?

In six months of testing Supabase applications, the most common critical finding was not a novel exploit - it was a misconfigured RLS policy that exposed every row in the database to any authenticated user.

PostgREST, the API middleware layer sitting between a Supabase client and PostgreSQL, also has its own CVE history. CVE-2022-35912 allowed authenticated users to escalate to superuser privileges by exploiting the db-pre-request configuration hook, bypassing all RLS policies entirely. This was patched in PostgREST 10.0.0 in August 2022 and pushed to hosted Supabase projects, but it is a reminder that Supabase API security testing is not limited to application-layer configuration. The API surface is wide enough to have attracted critical vulnerabilities at the middleware level itself.

Over the last six months, I have tested multiple Supabase apps for customers as a penetration tester and contributed multiple issues to the Supabase vulnerability disclosure program. Through this, I have gained some knowledge which I feel applies to most applications built on Supabase, which I will try to distill below. I have tried to write this as a primer and keep the tips basic but useful. This will in no way be comprehensive, but I hope it will allow you to start testing with confidence and avoid the overwhelm of a new tech stack.

Authentication

Supabase provides a solid authentication base. Email/password authentication works and is secure with the flick of a switch. OAuth requires some config but has sensible defaults that make common pitfalls hard to fall down.

The authentication configuration surface in Supabase is wide: JSON Web Token (JWT) signing keys, rate limits, and session behaviour are all configurable, and any of them can be misconfigured. It is worth creating a free account on Supabase and going through these options to understand what a developer could have changed and may be vulnerable. For a systematic approach, the OWASP Application Security Verification Standard (ASVS) provides structured authentication test cases, and WSTG-AUTHN covers the full authentication testing methodology.

One common issue I've run into with Supabase is Multi-Factor Authentication (MFA). In my opinion, it is not as deeply integrated with the platform as the rest of the authentication options. Although it is a toggle to turn on, it has to be manually applied to each endpoint using row level security. In my experience, this has led to MFA bypasses and just broken MFA functionality in general. I would advise testing this extensively.

Supabase's handling of password resets and email verification has some quirks worth understanding. Unusually, Supabase allows you to bypass authentication with a forgot password link. They act essentially like magic links which act as one-time login links bypassing traditional auth. From here, a developer must create a frontend which hits an endpoint to change the password. This can also be used instead of email verification when creating an account. Although this is unusual and feels like it could be wrong, I have not yet found an instance where this causes any security issues.

A final quirk on forgot password is that the old password is not required in the normal Supabase flow. This leads to a potential issue: if an attacker could gain access to a valid bearer token, they can change the user's password to create persistence and possibly block the user from accessing their account.

Authorisation

If we're talking about authorisation, we are mostly talking about row level security (RLS). It has already been mentioned, but in this section, we will go into it in detail. RLS is the single most important part of Supabase when it comes to information security. If RLS is off, every authenticated (or even unauthenticated) user can read or write to _any_ table in your database, a catastrophic failure point. Supabase will strongly warn users when they have it switched off, so I have not often seen it off entirely. However, due to its potential complexity, I have seen it implemented with holes in.

Broken access control - the vulnerability category RLS failures fall into - is OWASP's single most prevalent web vulnerability class. According to the OWASP Top 10 2021, 94% of applications were tested for some form of broken access control, with 318,487 total occurrences across the dataset and an average incidence rate of 3.81%. It moved up from fifth position in the previous edition. RLS misconfiguration is a textbook instance of this class, and in Supabase applications it is where I have consistently found the most impactful findings.

A practical note on default behaviour: tables created via raw SQL or the SQL Editor in Supabase do not have RLS enabled automatically. Developers must add ALTER TABLE ... ENABLE ROW LEVEL SECURITY manually. Tables created through the Supabase Table Editor UI do have RLS enabled by default, but production schema management almost always involves SQL migrations - which means RLS is opt-in in the environments where it matters most.

Test every endpoint that can be found and try to retrieve all information. Ensure that excessive data exposure or Insecure Direct Object References (IDOR) are not possible - see OWASP WSTG-ATHZ-04 for the full IDOR testing methodology. You can find the different ways to query the PostgREST API in the documentation. An interesting trick to return all accounts when a table is being queried with UUIDs is to use the greater than (gt) or less than (lt) operator. Although a UUID is not commonly seen as numerical, it is possible to use gt and a UUID with all 0's and it will show all UUIDs it can access.

id=gt.00000000-0000-0000-0000-000000000000

A final thing to understand about authorisation on Supabase is the difference between an anon key and a service role key. Both are in the JWT format. An anon key is public and will be sent with every request whether you are authenticated or not - it is safe to embed in frontend code because it operates with the anon Postgres role, which has only the permissions you explicitly grant via RLS policies. A service role key (service_role) bypasses all RLS policies and grants full read/write access to the database. Treat it as a master credential - its exposure is a complete database compromise.

The table below maps Supabase's key security settings to their default state, misconfiguration risk, testing approach, and whether the Security Advisor alerts on them.

SettingDefault StateRisk if MisconfiguredHow to TestSecurity Advisor Alert?
Row Level Security (RLS)Disabled for SQL-created tables; enabled for Table Editor tablesAny authenticated or anon user can read/write all rowsQuery table without auth; query as a different user's JWTYes - check 0013 ("rls disabled in public")
Service role key (service_role)Hidden server-side; must never appear in client codeFull database read/write bypassing all RLS; superuser-equivalent access for anyone who finds itSearch frontend JS bundles for service_role; check Vercel/Netlify environment variable exposureYes - check 0007 ("policy exists rls disabled")
Anon key (anon)Publishable; safe to expose client-side when RLS is correctly configuredIf RLS is disabled or policies are too permissive, anon key grants unintended read/write to all rowsUse anon key directly in API calls; test what data is returned without authenticationPartial - flags missing RLS, not anon key exposure directly
MFA enforcementOptional - configurable per project, not enforced by defaultMFA bypass possible if not applied per-endpoint via RLSAuthenticate without completing MFA challenge; check if JWT is accepted after first factor onlyPartial - flags MFA not enabled; policy enforcement gaps are not auto-detected
JWT signing keySupabase-managed by default (HS256)JWT forgery if custom secret is weak or accidentally exposed; algorithm confusion attacks possibleCheck Supabase config for custom JWT secret; test JWT algorithm confusion (HS256 vs RS256)No
Email verificationEnabled by defaultAccount enumeration via differing error messages; magic link misuse; unverified accountsTest signup and forgot-password flows for error message differencesNo

Testing the Frontend

The frontend is entirely disconnected from Supabase and should be threat modelled separately. That said, I have found that a lot of people that use Supabase are inclined to use hosted options and modern frameworks. I would expect a Supabase user to use something like Vercel, or something AI-powered like Lovable, if going the hosted route. If going the self-hosted route, I would expect a modern framework like Vue or React.

When testing the frontend, Cross-Site Scripting (XSS) is a productive starting point. In React and Vue applications, look for any instance where user-controlled data is rendered via dangerouslySetInnerHTML (React) or v-html (Vue) - both bypass framework-level output encoding and are a common source of reflected and stored XSS in Supabase-adjacent frontend code. Lovable-generated applications warrant extra attention here: the AI-generated scaffolding can produce patterns that pass a superficial review but leave injection points open.

Vercel deployments introduce their own attack surface worth checking separately. Exposed environment variables are a common finding - if a developer has placed the Supabase service_role key in a Vercel environment variable that is accessible to client-side edge functions or accidentally logged, the impact is a full database compromise. Check the network tab and any exposed Vercel project configuration for environment variable leakage.

Client-Side Path Traversal (CSPT) is also worth exploring - this is a class of vulnerability where an attacker can manipulate a relative URL used in a client-side fetch call, redirecting the request to an attacker-controlled endpoint or triggering unintended API calls. A detailed breakdown of the CSPT exploitation path is available at Doyensec's write-up. Go forth, figure out the weaknesses, and find an XSS or even cooler a CSPT.

Security Advisor

Finally, let's talk about the Supabase Performance and Security Advisors. This is a tool Supabase includes within its dashboard. It will try to warn developers about common security pitfalls they are running into and how to fix them. The tool runs 24 automated checks covering a range of security and performance issues. The security-relevant checks include: check 0013 ("rls disabled in public"), which flags tables in the public schema without RLS enabled; check 0008 ("rls enabled no policy"), which flags tables where RLS is on but no policies are defined; check 0024 ("permissive rls policy"), which catches overly broad policies; and check 0015 ("rls references user metadata"), which flags policies that reference user-modifiable metadata and may be bypassable. In my experience, developers will either:

  1. Follow this correctly and have quite a hardened setup
  2. Get swamped early by alerts they don't understand, have notification fatigue, and ignore it entirely

This is invaluable when trying to explain to a client how to fix issues. If you're reporting it, it's likely Security Advisor will have a notification that you can point to. It's no silver bullet, but resolving all these issues will go a long way for application security.

Where Should You Focus Your Supabase Security Testing Time?

Testing Supabase is like testing any other modern backend, but its combination of Postgres, REST, and frontend-centric workflows makes it easy to overlook critical misconfigurations. The shared responsibility model between the developer and Supabase is documented and should guide where you spend your testing time: Supabase is responsible for platform infrastructure, but every configuration decision, every RLS policy, and every API key handling decision sits with the developer.

For prioritisation, I would rank it in this order: start with authorisation and RLS. This is where the highest-impact findings live, and broken access control at the database layer has the worst blast radius. Next, authentication: work through the MFA bypass scenarios, the JWT configuration surface, and the forgot-password flow. After that, the frontend: XSS, CSPT, and Vercel environment variable exposure are all realistic findings in Supabase-adjacent stacks. Finally, use the Security Advisor as a checklist to triage any issues you have missed and to give your client a clear remediation path.

When a developer veers off Supabase's beaten track, your testing instincts should kick in - that's often where the interesting findings start.

Supabase is free, fast to spin up, and well worth a tester's time. A bit of hands-on exploration goes a long way and might just net you your next bug.

Happy hacking!


FAQ

What is Supabase row-level security (RLS) and why does it matter for security testing?

Row-level security (RLS) is a PostgreSQL feature that Supabase uses as its primary authorisation mechanism. It controls which rows a given user can read or modify at the database level. When RLS is disabled or misconfigured, any authenticated (or even unauthenticated) user can read or write to any table via the PostgREST API. For penetration testers, this makes RLS the single highest-priority check in any Supabase engagement.

What is the difference between the Supabase anon key and the service role key?

The anon key (anon) is a publishable key intended for unauthenticated and public requests. It is safe to embed in frontend code, provided RLS is correctly configured. The service role key (service_role) bypasses all RLS policies and grants full read/write access to the database. It must never appear in client-side code, JavaScript bundles, or version control. Finding a service_role key in a frontend bundle is a critical finding: it grants the equivalent of superuser database access to anyone who reads the source.

How do you test for MFA bypass vulnerabilities in Supabase?

Test whether the application accepts a valid JSON Web Token (JWT) after only the first authentication factor is completed, without requiring the MFA challenge to finish. Supabase's MFA is a toggle at the project level but must be enforced per-endpoint via RLS policies. Applications that enable MFA at the UI level but do not enforce it in RLS are vulnerable to bypass: authenticate normally up to the first factor, extract the JWT, and test whether it is accepted by protected API endpoints.

What does the Supabase Security Advisor actually check?

The Supabase Performance and Security Advisors tool (accessible in the Supabase dashboard) runs 24 automated checks. The most security-relevant are: check 0013 (tables in the public schema with RLS disabled), check 0007 (policies defined on tables where RLS is not enabled), check 0008 (RLS enabled but no policies defined, creating a deny-all state that may indicate developer error), check 0024 (overly permissive RLS policies), and check 0015 (RLS policies that reference user-modifiable metadata). The Security Advisor does not currently cover JWT signing key strength, MFA enforcement gaps, or custom domain/CORS misconfigurations.

What is CVE-2022-35912 and why is it relevant to Supabase security testing?

CVE-2022-35912 is a privilege escalation vulnerability in PostgREST, the API middleware layer that Supabase uses to expose PostgreSQL as a REST API. The flaw allowed authenticated users to escalate to superuser privileges by abusing the db-pre-request configuration hook, bypassing all RLS policies. It was patched in PostgREST 10.0.0 (August 2022) and Supabase pushed the update to hosted projects. It is a useful reference case because it demonstrates that Supabase API security testing must extend beyond application-layer configuration to the middleware and infrastructure layers.

Expert Guidance

Put this guide into practice

Our CREST-certified penetration testers can validate your configuration, identify gaps, and provide an independent audit report.