September 29, 2026

Is Your Supabase Security Leaking PII, Passwords, or Auth Tokens Right Now?

by
Abhijay Bhatnagar
September 29, 2026
Copy link to blog

If you use Supabase, assume this is possible in your app until you prove it isn’t. UpGuard researchers reported over 16,000 misconfigured Supabase databases with readable tables exposing PII, and in some cases passwords and auth tokens. They didn’t “hack” anything fancy. They looked for Supabase-backed domains at scale (~300,000), probed for accessible user data (even when it wasn’t literally called users), and used table schemas to infer what was leaking.  The scary part isn’t Supabase itself. It’s how easy it is to ship an app with security assumptions that are wrong.

How researchers found 16,000+ exposed Supabase databases (and why it worked)

UpGuard didn’t need zero-days or fancy exploitation to spot misconfigured Supabase databases. They treated the internet like a giant test harness.

Here’s the plain-English version of the approach: they started with a dataset of around 300,000 domains that showed signs of using Supabase, then systematically checked whether data could be read out of the backend without proper access controls . If your app is wired so an unauthenticated request can pull rows from a table, that’s not a “breach” in the movie sense. It’s just… your API answering.

Step 1: Find apps that look Supabase-backed

At scale, you don’t hand-check apps. You look for patterns that suggest Supabase is in use, then you test what a random user can access . This is why exposure can feel so unfair: you can be a small app, not on anyone’s radar, and still get caught in a wide scan.

Step 2: Probe for the obvious target (users)… then pivot fast

UpGuard’s researchers checked for a users table across those Supabase-backed domains . Sometimes, queries returned actual database pages/data. Other times, the response suggested the users table wasn’t there—yet some other table was accessible under a different name .

That matters because a lot of apps don’t store user data in a neat users table. They store it in:

  • profiles
  • customers
  • accounts
  • members
  • contacts
  • leads
  • people

If the scan only looked for “users,” it would miss a ton. UpGuard didn’t stop there.

Step 3: Use table schemas to figure out what’s leaking

Once a table is readable, the schema becomes a roadmap. UpGuard used table schemas to infer exposed data types across the set . A column name like email, phone, password, token, refresh_token, otp, or ssn_last4 doesn’t need deep interpretation. It tells you exactly what kind of mess you’re dealing with.

This is the part teams underestimate: attackers don’t have to guess what your data means. Your database structure usually explains it for them.

Why this worked (and why you should assume you’re not special)

This worked because misconfigured Supabase security often fails “quietly.” When Row Level Security (RLS) is missing or ineffective, the system can behave like it’s functioning normally—your frontend still loads, your app still “works”—but it’s effectively serving private tables like public content .

A good mental model is simple:

  • If an unauthenticated request can query it,
  • someone else can run that same request,
  • and they can automate it.

And at internet scale, “someone else” isn’t always a human sitting at a laptop. It’s a script.

What was exposed in the real world: it wasn’t just emails

Once a Supabase database is readable, the leak usually looks boring. A normal JSON response. A clean table output. No alarms. Just sensitive data exposure hiding behind “it worked on my machine.”

UpGuard’s analysis found that PII showed up in more than half of the exposed Supabase databases they reviewed, with a smaller subset containing passwords and authentication tokens . They also believed a very small set of the exposed data likely included credit card data . That’s the part people miss: misconfigured Supabase apps don’t leak one field. They leak whatever you stored.

What “PII” meant in practice

This wasn’t limited to login emails. It was operational data that can be used for stalking, fraud, extortion, or account takeover:

  • Contact details tied to real activity and locations
  • Identity and payment account data
  • Private messages and communications logs

Examples UpGuard highlighted (read this slowly)

These aren’t theoretical “could happen” scenarios. These are the kinds of records that showed up during investigation:

  1. U.S. valet service: exposed 100,000+ customer records, including contact details, license plates, and visit history
  2. Canadian immigration service: nearly 5,000 user records, including 884 plaintext passwords
  3. India-based adult creator platform: exposed sensitive identity data, payment accounts, and 100,000+ private messages
  4. Philippines-based OTP service: exposed 2,000+ users and 100,000 SMS messages, including messages that looked unrelated to the service itself
  5. African government consulate: exposed records for 25,000 people, including addresses and emergency housing locations

Why “auth tokens” changes the severity fast

Leaking PII is bad. Leaking auth tokens can be worse, because it can turn into instant access—session hijacking, unauthorized API calls, and quiet data pulling that looks like a real user .

If you’re building on Supabase, take this as a practical warning: any table that contains passwords, JWTs, refresh tokens, OTP logs, messages, addresses, or payment metadata has to be treated like live ammo.

Root causes: RLS gaps, key misuse, and “defaults” people misunderstand

When Supabase data leaks, it’s rarely because Supabase is “wide open.” It’s usually because your app made it open—by accident—through two very specific mistakes UpGuard called out: missing/ineffective Row Level Security (RLS) and misuse of public keys .

1) Missing or ineffective Row Level Security (RLS)

RLS is the guard that decides which rows a given request is allowed to read or write. Without it, a table can behave like a public dataset.

What “ineffective” looks like in real apps:

  • RLS not enabled on a table you assumed was protected
  • Policies exist, but don’t match reality (wrong role, wrong condition, wrong table)
  • A policy that accidentally turns into “allow read for everyone” because the logic is too broad
  • You locked down users, but forgot the “shadow user tables” like profiles, customers, messages, otp_logs, audit_events

Here’s the hard truth: if a table is reachable via your Supabase API and no policy blocks anonymous reads, your endpoint becomes “public data” even if you never meant it to be.

2) Misuse of public keys (the “anon key isn’t magic” problem)

UpGuard also pointed to misuse of public keys as a cause of exposure .

Teams get tripped up here because the anon/public key is meant to be used client-side. That sounds safe… until you remember what actually enforces access:

  • The key identifies the project and role
  • RLS policies are what stop the data

So if RLS is missing or sloppy, a public key plus a public endpoint is enough to read tables. No “hacking.” Just normal requests.

3) The human pattern: shipping fast, misunderstanding defaults

UpGuard’s take was blunt: business type didn’t matter because the mistake is the same—people didn’t understand the database configuration . They also described a common thread where sites are created by AI coding agents and the humans behind them are unaware of the configuration .

That tracks with how modern apps get built:

  • Someone scaffolds auth, CRUD, and admin pages in a weekend
  • The app “works”
  • Nobody does the uncomfortable test: What can I read when I’m not logged in?

If you want a clean takeaway, it’s this: Supabase won’t guess your intent. If your policies don’t explicitly block access, your data can quietly become public.

The tighten-now Supabase checklist (15–30 minutes that actually matters)

If the root cause is “we assumed defaults were safe,” the fix is simple: stop assuming. Prove what’s public, what’s authenticated, and what’s truly locked down.

UpGuard explicitly urged Supabase users to run Supabase’s own guardrails—Advisors and the API security guide—to identify exposure risks and mitigate them . Use that as your starting gun.

A fast, high-impact Supabase security checklist

  1. Inventory every table that could contain sensitive data

Don’t just review users. Hunt for “user tables with different names”:

  • profiles, customers, members, accounts
  • messages, threads, comments
  • otp, sms, email_logs
  • sessions, tokens, refresh_tokens
  • audit, events, activity

If it can identify someone, help log them in, or reveal communications, treat it like PII/auth material.

  1. Verify RLS coverage on every sensitive table

For each table above, confirm:

  • RLS is enabled (not “we wrote policies somewhere”)
  • Policies exist for the roles you actually use (common gotcha: you test as an admin/service role and think it’s fine)
  • There is no accidental broad SELECT policy for anonymous access

Quick sanity test: if you removed your frontend and only kept the Supabase URL + anon key, would you still be able to read rows you shouldn’t?

  1. Test policies like an attacker would (not like you would)

Do two tests per table/view:

  • Unauthenticated request (no session/JWT): should return nothing sensitive
  • Authenticated as a normal user: should only return that user’s rows (or intended shared rows)

If you can’t easily run these tests, that’s already a signal your access model isn’t well understood.

  1. Audit your “public endpoints”

Common ways teams accidentally expose data:

  • Read-only endpoints meant for “public pages”
  • Search endpoints that return full objects
  • Client-side queries that include extra columns “just in case”

Lock down anything returning data without auth unless you’re 100% okay with it being indexed, scraped, and reposted.

  1. Run Supabase’s built-in guidance

Supabase isn’t leaving you alone here. Start with:

  • Supabase Advisors
  • Supabase API security guide

Treat the output like a punch list, not a suggestion.

One more move that cuts blast radius: store less PII

A lot of Supabase “leaks” hurt because raw identifiers are sitting in tables everywhere—real emails, real phone numbers, real names.

If you don’t truly need raw contact info, consider using Cloaked identities (masked email/phone) so your database stores less direct PII in the first place. It won’t fix RLS mistakes, but it can make the worst-case outcome meaningfully less damaging.

If you think you were exposed: a practical incident-response playbook

If there’s even a chance your Supabase tables were publicly readable, treat it like an incident. UpGuard said it notified owners when deeper analysis found significant exposure . Don’t wait for a notification to act.

Phase 1: Contain the blast radius (same day)

  1. Prove what’s reachable from the outside
  • Test from a clean environment (incognito, no session) and try the same queries your app makes.
  • Check for “not-a-users-table” leaks: profiles, customers, members, messages, otp, logs, tokens.

Rule: don’t trust the dashboard alone. Validate with fresh unauthenticated requests.

  1. Pull evidence before you change too much
  • Export/retain relevant request logs and query logs so you can answer: who accessed what, when, and how often?
  • Snapshot the current RLS + policies so you can later explain what went wrong.
  1. Rotate what attackers would reuse

UpGuard found exposed databases that included authentication tokens in some cases . If tokens were exposed, assume replay.

Rotate, in this order:

  1. Any leaked auth tokens / refresh tokens (invalidate sessions where possible)
  2. API keys/secrets used by server-side integrations
  3. Service role key handling and storage (make sure it’s never shipped to the client)

Phase 2: Fix access control, then re-test like a stranger

  • Enable/confirm RLS on impacted tables.
  • Tighten policies, then rerun the same unauthenticated checks that showed exposure.

If your fix depends on “the UI doesn’t show it anymore,” it’s not a fix. Your goal is: the request fails, every time.

Phase 3: Customer-facing damage control (do this fast, do it clean)

If passwords were exposed

UpGuard observed a case with plaintext passwords . If that’s even remotely possible in your app:

  • Force password resets.
  • Invalidate active sessions.
  • Add extra friction temporarily (step-up auth) for sensitive actions.

Notify users when required (and when it’s the right thing)

  • Tell users what data types were involved (PII, tokens, messages).
  • Give clear actions: reset password, watch for phishing, watch for SIM-swap/OTP scams.

Phase 4: Monitor for the messy aftermath

Token and OTP-related leaks aren’t “one and done.” Watch for:

  • Account takeover attempts (login spikes, unusual IPs, repeated failures)
  • OTP/SMS fraud patterns (repeated sends, abnormal destinations)
  • Sudden changes to emails/phone numbers, password resets, or new device sign-ins

The goal isn’t to look perfect. It’s to move fast, keep receipts, and stop the bleed before it turns into months of quiet abuse.

‍

Free number scan to see what info about you is exposed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
View all
Data Breaches
October 12, 2026

If Your AI Safety “Test” Touches Real Government Websites, It’s Not a Test Anymore

Data Breaches
October 12, 2026

Bought a Ledger Recently? Do This Now to Protect Your Hardware Wallet

Data Breaches
October 12, 2026

Would you spot a malvertising campaign hiding a fake Claude installer in your search results?