Security on retainer · Supabase apps in production
One permissive policy exposes every row.
We find it, fix it, and keep proving it.
ShipLock audits your live Supabase project — row-level security, auth configuration, storage, grants, dependencies and the routes that reach them — on every pull request rather than once a quarter. Tenant-isolation failures are demonstrated against a disposable copy of your schema, not inferred from reading policy text. Findings arrive as migration pull requests you review and merge.
Example audit — anonymized
● on watchRepresentative output: severity, the asset, and a remediation you can merge. Passing checks are shown alongside failing ones — a control that was verified is a result.
The watch, in practice
A point-in-time assessment expires at your next deploy.
Security posture is a property of the current commit, not of the codebase in general. One agent-authored migration can drop a policy that a report from last week certified. So the audit re-runs on a schedule and on every pull request, and each pass is diffed against the last — you are alerted on new findings, not re-alerted on known ones.
Every pull request, re-audited
One GitHub App installation. Every pull request is re-scanned before merge: committed credentials, dependencies with known advisories, workflow permissions, and changes to the code paths that enforce access control.
Deep audits on schedule, critical checks hourly
A full sixteen-check pass every 48 hours. Between them, an hourly pass covering the four failures that appear without a deploy — RLS switched off, a bucket made public, credentials exposed at the origin, a secret key in use.
A live edge at your front door
A middleware snippet mirrors auth-route metadata to us and fails open by construction: if we are slow or down, your request proceeds. Credential stuffing and enumeration are scored per source, and a source is blocked only on unambiguous signal — false positives here lock out paying users, so the threshold is deliberately conservative.
Auth & access
Session handling, token configuration, rate limiting on the auth endpoints, and whether privileged routes actually verify authorisation rather than only authentication.
Data exposure
Whether row-level security, column grants and storage policies refuse the queries they are meant to refuse. This is the surface behind nearly every documented breach of an AI-built application.
Configuration
Credential handling, response headers, source maps, CI workflow permissions, and dependencies carrying published advisories.
Injection & logic
Untrusted input reaching a query or a template, mass assignment on write endpoints, and server-side request forgery through user-supplied URLs.
Sixteen checks span those four surfaces, mapped to the OWASP Top 10:2025 — including what we can't catch, named honestly →
Something to send when they ask.
A shareable page showing which controls are assessed against your project, the cadence, and when each last ran. It publishes posture and timestamps, never your specific findings — a report that enumerated your open issues would be a target map. It is not a SOC 2 report and does not substitute for one; it is a verifiable answer for the period before you have one.
Onboarding takes your project URL and the publishable key your client already ships to every visitor. Deeper checks use a read-only Management API grant you authorise over OAuth and can revoke at any time — the transport refuses anything that is not a single SELECT. Secret keys are never stored; if one is submitted it is flagged and discarded. Autonomous remediation is off by default and, when enabled, is bounded to reversible actions with the inverse computed before the change.
Why this matters now
Three reasons this becomes urgent before anything leaks.
You likely know roughly where your gaps are. What changes once you have real users is not the technical risk — it is that the risk acquires a counterparty, a deadline and a regulator.
The first serious customer asks you to prove it.
Not a breach — a security questionnaire. Procurement wants to know how access is controlled, who verifies it, and how often. SOC 2 Type I answers that for $20,000 and three months. Before that, a live posture report showing the controls assessed and their last run is a defensible answer rather than an assurance.
The dangerous policy looks exactly like a safe one.
A table with RLS enabled and a USING (true) policy refuses anonymous reads, so it passes any external probe holding only a publishable key. Every authenticated user still reads every row. This is the most common critical finding on Supabase, and detecting it requires evaluating the policy as a signed-in caller — which is what the sandbox exists to do.
Customer data makes it a legal matter.
Once personal data is exposed, obligations attach regardless of company size: notification to affected users, response to privacy regulators within statutory deadlines, and civil liability. None of these scale down because you are a team of two.
This isn't hypothetical. CVE-2025-48757: 170+ live apps built with an AI builder were found serving names, emails, and financial data to anyone who asked — one missing database rule, rated CVSS 9.3. We wrote up what actually happened →
Proof, not inference
We exploit a copy of your schema, never your app.
Reading a policy tells you what it should do. Running against it tells you what it does. For tenant isolation — the failure where one signed-in customer reaches another's rows — we settle the question by trying it, inside an environment built for the purpose and destroyed afterwards.
The arena holds your schema and policies and none of your data. The accounts in it are synthetic, so there is no row belonging to a real person for anything to reach. A control query runs first: if the arena cannot return the caller's own row, the result is discarded rather than reported as clean — a broken sandbox that says “no leak” is worse than no sandbox at all.
Where the fixed probe finds nothing, a reasoning agent proposes further queries. It contributes ideas, never authority: every statement it composes is checked by a deterministic guard that permits read-only queries inside the disposable schema and refuses everything else, and each attempt — including the refused ones — is kept as evidence. We never point it at anything you operate. The full scope, including where each capability stops →
The handoff
Remediation is a diff, and the diff is yours to approve.
Each finding ships with its remediation. Schema and access-control changes open a migration pull request on a new branch — you review it, edit it, merge it, and your own pipeline applies it. Application logic is never machine-authored; those open as draft pull requests for you or your coding agent to finish. Nothing is applied silently, and every action carries a stored inverse.
Example fix — anonymized · one reviewable PR per finding
supabase/migrations/…_shiplock_enable_rls_invoices.sql
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY owner_only ON invoices
USING (auth.uid() = user_id);
Opened as a pull request against a new branch, never merged by us. Auth, RLS and schema changes stay under your review by design — the blast radius of a wrong policy is your entire user base.
Or don't leave your editor
Connect ShipLock to your coding agent.
ShipLock exposes its findings over MCP. Add it to Claude Code, Cursor or Codex and your agent pulls open findings and their remediations into context, then writes the changes in your working tree — still a diff you review before it lands.
Terms
One engagement. Three ways to pay for it.
The same product on every term — nothing is held back on the monthly plan. Longer terms are simply cheaper, paid once, with no auto-renewal and no cancellation fee.
For scale: a first-year SOC 2 runs $20,000–$60,000 across the audit, the compliance tooling and your own engineering time. It answers a different question — organisational control design — on a longer clock. This is the technical layer underneath it, and the evidence trail it produces is the kind an auditor later asks for.
Monthly
$49/month
The engagement, billed as you go.
- Sixteen checks across four attack surfaces, continuously
- Every pull request re-audited; deep scans every 48 hours, critical checks hourly
- Fixes delivered as reviewable pull requests you merge — never applied to your database by us
- A live edge that blocks credential stuffing, scanners, and floods — fails open, never a real user
- Alerts only when something new appears — silence means you're clean
- Shareable Verified report for your own customers and investors
- First 7 days free — cancel before you're charged
A one-time scan characterises a single commit. A retainer characterises a moving codebase: every pull request, hourly on the fast-moving checks, and in full depth every 48 hours.
What we won't promise
No control set eliminates risk. Ours reduces a specific, well-understood part of it.
Breaches of applications at your stage are overwhelmingly not novel: a missing access-control rule, an exposed credential, an unpatched dependency, an unauthenticated route. That class is enumerable, testable and closeable, and it is the class we address — continuously, so a regression is caught by the next pass rather than by a customer. Targeted attacks, insider access and flaws in your own business logic are outside it, and we say so in each report rather than at the end.
We move you to a hard target — the app that isn't worth an attacker's effort. Not to the far end. Nobody lives there, and anyone who says they can take you there is selling you something.
Where a check does not apply or could not run, the report says so explicitly. An absent result is never rendered as a pass — a repository we failed to read and a repository with nothing to find produce different output, because treating unknown as safe is how assessments mislead. For what no scanner can evaluate — your authorisation logic, your business rules — we supply the review prompts to audit it yourself.
Get started
Connect the project. Get the first findings in 90 seconds.
Sign in, start the trial — 7 days free before the first charge — then paste your Supabase URL and anon key. Nothing we ask for is a credential beyond the public key your frontend already ships. The first audit runs immediately.