Case study Demo project

Three planted holes in a demo Supabase project, and what each check shows

Demo project built by PatchAndShip for testing; not a real customer. All data is fake.

We built a demo Supabase project, patchandship-demo, with fake data, planted three common security holes, and compared what each check reports. Each one answers a different question, so this isn't a ranking.

The three holes

  1. RLS turned off. The table public.demo_customers has row level security disabled. The anon and authenticated roles have select, insert, update and delete grants.
  2. A read policy that allows everyone. On public.demo_orders RLS is on, but the policy "demo: anyone can read orders" is for select to anon, authenticated using (true). It looks protected, but anyone can read every row.
  3. A public file in a public bucket. The public bucket demo-public holds a fake invoice, FAKE-invoice-0001.txt. A signed-out request to its public URL returned HTTP 200 (245 bytes). Listing the bucket as anon returned an empty list, so the file is reachable only by its link.

Supabase Security Advisor

The Security Advisor is free and built in. It lints your schema and configuration. On the demo it reported 1 error, 0 warnings and 0 suggestions:

Supabase Security Advisor on the PatchAndShip demo project, showing 1 error: "RLS Disabled in Public" on public.demo_customers, with 0 warnings and 0 suggestions.
Demo project built by PatchAndShip for testing; not a real customer. All data is fake. Screenshot taken Oct 15, 2026.

Supabase's Security Advisor flagged the table with RLS turned off. It didn't flag a table whose RLS policy lets anyone read every row, because its always-true-policy check skips read policies by design, and it doesn't flag public buckets that serve files by link, which is how public buckets are meant to work but easy to misuse.

Both are design choices. A using (true) read policy is often a real public catalog. The Advisor can't know which you meant.

Our open-source RLS checker (not yet released)

check-my-supabase is an open-source script we're preparing. It is not published yet. It checks what a signed-out visitor can actually read, with read-only HEAD requests as the anon role. It never downloads rows.

We ran version 0.1.0 against the demo on Oct 15, 2026:

  READABLE   demo_customers  returns rows (4)
  READABLE   demo_orders     returns rows (4)

2 tables return rows to anyone with your public key.

Demo project built by PatchAndShip for testing; not a real customer. All data is fake.

Its limits: it shows that a table is readable, not why, so it can't tell hole 1 from hole 2. It doesn't test writes or Storage, or know whether a table should be public.

Writes matter. On Oct 15, 2026, we sent a signed-out insert to demo_customers with only the public key. It worked, and we deleted the fake test row right away. The same settings leave updates and deletes open too; we tested only the insert. The same insert into demo_orders was refused with error 42501.

Our free website check

The free check at patchandship.com/check.html reads your public homepage, scripts and headers. It never queries a database. The demo has no website, so we didn't run it. From its current code:

  • Holes 1 and 2: not detected. It calls your public Supabase key normal and points you to the Advisor.
  • Hole 3: noted only if your code links to demo-public. It never opens the file.
  • It covers what the others don't: secret keys in public JavaScript and missing security headers.

What the paid fix adds

Security Fix ($149) covers RLS fixes on all tables, storage bucket policies, key scan and rotation guidance, and a short report. Fix & Deploy ($249) adds production deploy, env vars, auth redirects, custom domain, SSL and a smoke test of key flows. AI agents run the checks and draft the fixes, and a human engineer reviews and approves every change. For an exposed secret key, 'fixed' means we've removed it from your code in the change we deliver. You redeploy your app, set the key on your host and rotate it. We give you exact instructions. This demo hasn't had a paid fix, so there are no results to show.

Takeaway

A clean Security Advisor means your schema passed its lints, not that signed-out visitors can't read anything. Run the Advisor, then check what's actually readable.

Questions: patchandship@gmail.com

PatchAndShip Team