Harvey / Supabase security auditSupabase security

Supabase security audit — a real audit, not a scanner.

A Supabase security audit is a review of your app's authorization logic — RLS policies, auth guards, and multi-tenant boundaries — to find where users can access data they shouldn't. Automated scanners can't do this reliably, because the flaws live in your code's logic, not its syntax. Harvey reads the logic and then proves it against a live copy of your stack.

The vulnerability almost every Supabase app has at some point

Supabase's Row-Level Security is opt-in, not on by default. The most common flaw isn't a missing lock — it's a lock that looks fastened and isn't. The canonical example:

-- Looks correct. Lets ANY logged-in user read EVERY tenant's rows.
CREATE POLICY "users can read" ON documents
  FOR SELECT USING (auth.role() = 'authenticated');

That policy passes a glance, passes most automated checks, and quietly exposes every tenant's data to every logged-in user. Only reading the code — and then testing it — catches it. The same class includes service_role keys on client-reachable paths (which bypass RLS entirely by design), over-fetching API routes, unauthenticated endpoints, and IDOR.

Why a scanner isn't enough

Question about your appAutomated scannerHarvey audit
Finds known-CVE dependency issues
Flags syntax-level patterns
Understands your authorization logic
Tests whether tenant A can read tenant B's data live
Reviews RLS policy semantics, not just presence
Proves a finding is actually exploitable pen-test
Covers code health, not just security 10 modules
Tells you what it did not check ledger

Scanners are good continuous hygiene — keep yours. An audit answers the question a scanner structurally can't: does my app actually leak?

What Harvey checks on a Supabase + Next.js app

Ten modules, equal weight (security and code health). Among much else:

  • Multi-tenant isolation — every RLS policy reviewed for semantics, not just enabled/disabled: USING(true), wrong-column predicates, weak WITH CHECK, user-metadata trust, SECURITY DEFINER functions with unguarded writes.
  • service_role exposure — anywhere a service key sits on a client-reachable path.
  • Live cross-tenant pen-test — we seed two tenants on a local copy of your stack and try to read across the boundary. Proof, not a warning.
  • App Router boundaries — server→client data leaks, Server Action auth and validation.
  • Data classification — every PII/PHI/PCI column and where it lives.
  • Plus performance, duplication, dead code, maintainability, and test quality.

Full methodology → The Audit.

What you get

  • A findings report in plain English, ranked by blast radius — written for a founder, not a pentester.
  • For each finding: what it is, where it is, why it matters, and how to fix it.
  • A coverage ledger: exactly what we checked and what we didn't, with reasons. No silent gaps.
  • A re-audit credit: when you ship the fixes, we re-verify the critical findings once at no extra charge, if requested within 30 days of the original audit. Additional re-audits within that window are a paid add-on at 50% of the original audit price.
  • Optional investor-ready summary: a buyer-facing document for fundraise or acquisition diligence.

Pricing

No "book a call to hear the price." Priced by codebase size, measured automatically during the free scan:

  • Free scan — $0. Source-only, no credentials, same-day. Static findings from every module source alone can run, plus the ten-module coverage ledger, yours to keep.
  • Connected audit — from $500. The full review with real verdicts, plus a read of your live database: live RLS, Supabase advisors, PII in production.
  • Full audit — from $1,000. Everything in Connected, plus Harvey stands up a copy of your stack and proves findings with a live pen-test, and runs full mutation testing.

Full grid and size bands → Pricing.

FAQ

Supabase security audit — common questions.

Is the Supabase anon key supposed to be public?

Yes — the anon key is public by design. Your security comes from Row-Level Security, not from hiding the key. If RLS is missing or misconfigured, that public key becomes a master key to your database. That's the single most common failure we find.

Can't I just run an automated scanner?

A scanner checks patterns and known CVEs. It can't tell whether your users can read each other's data, because that depends on your authorization logic across multiple files. That's what an audit is for. Run both — they do different jobs.

How much does a Supabase security audit cost?

Harvey's free scan is $0. Paid tiers are priced by codebase size, measured automatically during the free scan: a Connected audit (adds a read of your live database) starts at $500, and a Full audit (which stands up and attacks a copy of your stack) starts at $1,000. Most boutique vibe-code audits run $1,500–$5,000 for source review only; a traditional pentest runs $4,000–$12,000. Harvey sits between: deeper than a source-only audit, faster and cheaper than a pentest firm.

Do you need access to my database?

Not for the free scan — it runs on source only, no credentials. Only the Connected and Full tiers read your production database, and only read-only. The Full-tier pen-test runs against a copy Harvey stands up on its own machines, never against your production.

What if my app was built with Lovable, Bolt, Cursor, or v0?

That's exactly who this is for. AI-built Supabase apps are where we most often find cross-tenant data exposure — and the fix is usually straightforward once you can see it.

Will you help me fix what you find?

Every finding comes with a fix. The audit includes a free re-verification of the critical findings after you ship the fixes.

Run the free scan on your Supabase app.

Source-only, no credentials, same-day. If it finds nothing worth going deeper on, don't buy a thing.