Scope
What is in the review is agreed in writing first: which surfaces, which roles, which records, and what may be touched on a running system.
A review commissioned to produce a document will produce one. This one goes looking for what is actually wrong — in our own code as readily as in the code we inherited — and it does not end when a patch is written. A finding is closed by a test that fails before the fix and passes after it, run against the system that is actually live.
| Finding | Class of issue | Where it sat | What it gave up | Closed by |
|---|---|---|---|---|
| F-01 Critical | Privilege escalation through a policy that guarded inserts and not updates Inherited | row-level policy, membership table | Any member could raise their own role to owner | Closed member updates own role → refused, row unchanged |
| F-02 Critical | Organisation bank details readable with the public key Inherited | a view that read around the row policy | Every organisation’s account and beneficiary, with no session at all | Closed anonymous read of the banking columns → zero rows |
| F-03 Critical | Refund claimable twice through two separate requests Our earlier work | refund endpoint, no lock and no idempotency key | Two settled refunds against one payment | Closed twenty concurrent refunds on one payment → one settlement |
| F-04 High | Webhook signature verification commented out Inherited | payment webhook handler | A forged paid event, and an order marked settled | Closed wrong signature → rejected; replayed event → ignored |
| F-05 High | Tenant taken from the request body rather than the session Our earlier work | report export | One field changed, and another tenant’s records exported | Closed export naming another tenant → refused, and an audit row written |
| F-06 Medium | Internal error detail returned to the client Our earlier work | error handler at the API edge | Stack frames and the database name, in a 500 body | Closed induced failure → a reference id, no stack, no database name |
five columns across — the log scrolls, and the last one is the evidence
The lowest of the six, and one of ours — press Try now to open another
F-06 · Medium · Our earlier work
Internal error detail returned to the client
error handler at the API edge
Stack frames and the database name, in a 500 body
Graded Medium: it hands an attacker the map rather than the door
a request forced to fail, from outside, against live
a stack trace and the database name in the 500 body
a reference id, no stack, and no database name
41
29
12
29 of 29
An illustrative log, drawn in code in this palette. Press Try now and open a finding: follow it to what an attacker got and to the test that closed it. The classes of issue and the shape of the assertions are the real work; the identifiers, the counts and the locations are invented. No client system is identified here, and none ever will be.
What is in the review is agreed in writing first: which surfaces, which roles, which records, and what may be touched on a running system.
Who would attack this, what they would want, and which records would end the conversation if they left the building.
Every path that writes, every rule that guards it, and every place a request is trusted to say who it is. Our own code is read the same way.
Nothing is filed until it is reproduced. What cannot be reproduced is closed as a false positive and reported as one.
Against the cause rather than the symptom, and reviewed by someone who did not write it.
A test that fails before the fix and passes after it, run against the live system and kept in the suite so the finding cannot come back.
A checklist finds the classes of issue every system has. It does not find the one your system has, because that one is made of your roles, your records, and a decision someone made under a deadline two years ago. So the review is written against how your system actually works — which is also why it goes after our own earlier work with the same appetite.
Findings are stated as classes here and anywhere else we publish. What was found in your system belongs to you, and is not a case study.
The code nobody on the team wrote, the endpoint everyone routes around, the rule that was added the night before launch. We will tell you what it gives up, and prove it is closed.