Each item says how it is tested and what it looks like when it is wrong, because "review your authorisation model" tells you
nothing about whether you have a problem today.
Almost always Authorisation on the data layer
How we check: We take the public key out of your own front end and query your API and database directly, signed out and signed in as an ordinary user, table by table.
What it looks like: Row Level Security disabled or written as a policy that permits everything, so any visitor can read the whole table. In Supabase-backed builds this is the single most common serious finding.
Often Object-level access between accounts
How we check: We create two accounts and try to read, edit, and delete each other’s records by changing the id in the request.
What it looks like: Endpoints that check you are logged in but never check the record belongs to you. Nothing is exposed to the public, and every customer can see every other customer.
Often Secrets in the client bundle and the repo history
How we check: We read the shipped JavaScript for keys, and walk the git history for credentials that were committed and later removed.
What it looks like: A service key, an admin token, or an email provider password sitting in the browser bundle, or removed from the current files but still live in an old commit and in every fork.
Sometimes Input handling and injection
How we check: We follow every input from the form to the query, looking for string-built SQL, unescaped rendering, and file uploads that trust their own filename.
What it looks like: Query strings assembled by concatenation, or user text rendered as HTML. AI-written code usually parameterises correctly, so this is rarer here than in hand-written code — but the exceptions cluster in the parts a human edited afterwards.
Almost always Server-side validation
How we check: We submit requests that your forms would never send: missing fields, wrong types, negative quantities, prices supplied by the client.
What it looks like: Validation that exists only in the browser, so anyone with curl can write whatever they want — including the price of the thing they are buying.
Often Session and authentication handling
How we check: We check token lifetime, where the session is stored, what happens on sign-out, and whether password reset can be used against another account.
What it looks like: Sessions that never expire, tokens kept where any script on the page can read them, or a reset link that does not invalidate after use.
Often Payment and webhook integrity
How we check: We check that webhook signatures are verified, that events cannot be replayed, and that what your database believes matches what the payment provider believes.
What it looks like: An unsigned webhook endpoint that anyone can post to in order to mark an order paid, or subscription state that silently drifts from Stripe after the first failed charge.
Often Dependencies and known advisories
How we check: We audit the lockfile against published advisories and separate the ones that are actually reachable from your code from the noise.
What it looks like: A generated project pinned to whatever resolved on the day it was built, carrying two or three packages with published vulnerabilities and no process for noticing the next one.
Often Transport, headers, and exposure
How we check: We check TLS, redirects, security headers, CORS, and whether admin routes, source maps, or debug endpoints are reachable from the internet.
What it looks like: An admin panel on a guessable path with no server-side role check, or a CORS policy set to allow every origin because that made local development work.
Often Personal data handling
How we check: We list what personal data you store, where it goes, which third parties receive it, and whether deletion is actually possible.
What it looks like: Analytics and error tracking capturing email addresses and form contents, no retention limit, and no way to fulfil a deletion request without hand-editing rows.