Skip to content
07.9Capability — Security review

A clean report is not the goal.

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.

What it looks like

What was found, and what closed it

Findings logexample · our code and inheritedSix of twenty-nine shownre-tested against the live system
FindingClass of issueWhere it satWhat it gave upClosed 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

One finding, opened in full

The lowest of the six, and one of ours — press Try now to open another

Finding

F-06 · Medium · Our earlier work

Internal error detail returned to the client

Where it sat

error handler at the API edge

What it gave up

Stack frames and the database name, in a 500 body

Why that severity

Graded Medium: it hands an attacker the map rather than the door

Closed by
Attempted

a request forced to fail, from outside, against live

Before the fix

a stack trace and the database name in the 500 body

After the fix

a reference id, no stack, and no database name

Press Try now to drive it yourself
افتح أخطر ثغرةورّني ثغرة من شغلناورّني بلاغًا ما صمد
Raised

41

Confirmed

29

False positives

12

Closed with a test

29 of 29

A findings log from a security review, ordered by severity, worst first. Six illustrative findings: a policy that guarded inserts but not updates, a public key that could read organisation bank details, a refund claimable twice through separate requests, a webhook whose signature verification had been commented out, an export that trusted the tenant named in the request body, and an error handler that returned internal detail to the client. Each row states where the issue sat, what it gave an attacker, and the assertion that closes it — a test that failed before the fix and passes after it, run against the live system. Three of the six are attributed to our own earlier work. Totals: forty-one raised, twenty-nine confirmed, twelve false positives, twenty-nine closed with a test. Below the log, one of them is opened in full: the error handler, one of ours, with what was attempted against it and what came back before the fix and after it. Press Try now to open another one and follow it a layer at a time — where it sat, what it gave up, why it was graded that way, and what was attempted from the outside to close it, with what came back before the fix and after it. One branch opens a report that did not hold, and was filed as a false positive rather than quietly dropped.

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.

How it runs

Six steps, and the last one is a test

01

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.

02

Model

Who would attack this, what they would want, and which records would end the conversation if they left the building.

03

Read

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.

04

Prove

Nothing is filed until it is reproduced. What cannot be reproduced is closed as a false positive and reported as one.

05

Fix

Against the cause rather than the symptom, and reviewed by someone who did not write it.

06

Re-test

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.

What you get

Evidence, not reassurance

FindingsEach one reproduced, with the exact request that did it
FixesWritten against the cause, reviewed by a second pair of eyes
Regression testsOne per finding, failing before the fix and passing after
False positivesListed with why they did not hold, never quietly dropped
ReportSeverity, impact and evidence, written for your engineers
Re-testThe whole suite run again against the live system after it deploys
What it connects to

The surfaces a review has to reach

Source controlWhere the fix lands, and where its test lives afterwards
CISo the regression test runs on every change from then on
DatabaseRow-level rules, roles, and the keys that can reach them
PaymentsSignatures, refunds, and anything else that moves money
IdentitySessions, tokens, and the boundary between one tenant and the next
LoggingWhere an attempt shows up after the fix, and who sees it
Custom, not configured

Your system, not a checklist.

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.

Next

Send us the part you inherited.

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.