Reference
Findings and product lines
Every problem PatchLabs reports, whether the Lab reproduced it in a rebuilt database or Code found it in your repo, arrives in the same shape with a stable ID. This page explains the four product lines and each field of a finding.
The four product lines
| Line | What it does | Produces |
|---|---|---|
| Lab | Rebuilds your database from supabase/migrations in a disposable Postgres with Supabase’s roles and grants, seeds fake rows, and reads every table as an anonymous visitor, a signed-in stranger and the owner. | Findings with line: "lab", proven by a real query |
| Code | Reads the repo without running it: keys in the code and the full git history, Edge Functions and their config, webhooks, CORS, admin checks in the browser, user_metadata role checks, raw HTML, Firebase rules, and dependency versions checked against OSV. | Findings with line: "code", with file and line |
| Fix | Writes the database fix as a migration, proves it in a fresh lab as the same three identities, asks you the business questions only you can answer, and hands it to your engineer to approve. Commit on GitHub in one click, or use MCP and CI. | The fix, the proof and fixed_in_lab on each finding. Automatic pull requests: coming with the GitHub App. |
| Watch | Re-checks on a schedule, shows what changed since last time, alerts by email and webhook, and signs every result. | Diffs, alerts, the badge and signed receipts |
| Live posture (part of Watch) | For a domain your team verifies, loads the public home page once a day like any visitor and grades HTTPS, the TLS certificate, security headers, cookie flags and mixed content. | Findings with line: "live", an A to F grade and a live badge (REST API) |
Lab and Code run on every check; there is nothing to switch on. Both work from the repo and the rebuilt lab database only: they never connect to your live app or database. Live posture is opt-in per app: PatchLabs never touches your database, and Live posture only loads your public home page, like any visitor, and only on domains you verify.
One finding shape
Each finding, from either line, has the same fields. This one is from our deliberately leaky demo app (fake data):
{"id": "PL-001", "line": "lab", "severity": "critical",
"title": "Anonymous visitor can read personal data",
"object": "public.profiles",
"file": "supabase/migrations/20261101090000_init.sql", "line_no": 12,
"evidence": "policy \"Profiles are viewable by everyone\" using (true); columns email, phone",
"proven": true,
"proof": "anonymous visitor read 2 rows with email and phone",
"fix": "Replace the open read policy with an owner-only policy",
"fixed_in_lab": true}id- The stable finding ID, such as
PL-001. Each has a page explaining it: the finding index. IDs never change meaning and are never reused. linelab,codeorlive: which product line found it. The report groups findings by line;livefindings come from Live posture and appear on the app page, not in a repo check.severitycritical,high,medium,loworinfo. See severity below.title- A plain-English summary. It can be more specific than the ID’s general title (for example naming the provider of a key).
object- What the finding is about: a table (
public.profiles), a bucket, a function folder or a source file (src/pages/Admin.tsx). file,line_no- Where to look in the repo. For Lab findings, the migration that created the rule; for Code findings, the exact line.
evidence- A short excerpt showing why. Keys are masked and no personal data is ever included.
proventruewhen the Lab reproduced it with a real query against the rebuilt database. Code findings arefalse: they are read from the code, not reproduced, and say so.proof- For proven findings, what the lab did and saw, such as “signed-in stranger read 3 rows owned by another user”.
fix- One line saying what to change. Database fixes also come as a full migration in the report.
fixed_in_labtruewhen PatchLabs Fix wrote a fix for this finding and it passed the lab proof.advisory- Dependency findings (
PL-023) only: the advisory id from OSV, such as a GHSA or CVE id.
Severity
Severity follows one question: who, outside the people meant to see it, can read or change the data?
| Level | Meaning |
|---|---|
| critical | Anyone on the internet, or anyone who signs up, can read personal data, change a whole table or make themselves admin. |
| high | Anyone who signs up can read personal data, a privileged function or webhook is open, or a user can act on another user’s data. |
| medium | A real weakness that needs a specific situation to matter. |
| low | Nothing exposed by itself. |
| info | Worth knowing, not a problem as found, such as a function without the sign-in gate that checks its caller itself. |
Dependency findings take the severity of their published advisory. Key findings depend on what the key can do.
Finding IDs
| Line | Live today | Coming (not tested yet) |
|---|---|---|
| Lab | PL-001 to PL-008: who can read each table, RLS off or empty, open writes, exposed definer functions, public buckets | PL-012 to PL-016: strangers changing rows, self-made admins, views skipping RLS, open storage policies, Realtime streams |
| Code | PL-009, PL-010, PL-011 (keys in code and history), PL-017 to PL-026 (functions, sign-up, user_metadata, admin checks, webhooks, trusted ids, dependencies, raw HTML, Firebase rules, CORS) | None |
| Live posture | PL-027 to PL-036: HTTPS not forced, certificate invalid or expiring, HSTS, Content-Security-Policy, framing, nosniff, cookie flags, mixed content, version headers, Referrer-Policy. Opt-in per app, on a verified domain | None |
Coming checks have pages so you can check your own project, but they won’t appear in a report until they ship. The changelog records when each one does.
Where findings appear
- The report page groups findings by line, most severe first, with the proof table for Lab findings. Reading a report.
- The API: a finished check’s
summarycarriesfindings(up to 200, in this shape) andcountsby severity, next to the existing summary fields. REST API. - Alerts and webhooks count new findings since the last check. Monitoring.
- The free RLS check uses the same IDs for PL-001 to PL-008, from the migrations as written (no lab).
Limits
Lab findings are only as complete as the migrations in your repo: rules created only in the Supabase dashboard are invisible. Code findings are pattern checks: they point at a file and line for a person to judge, and a clean result doesn’t prove the absence of every bug. Dependency checks need the public OSV API; offline, they are reported as skipped, not clean. None of this is a penetration test.