ContentsThe library

The Mistakes Behind Most Breaches

The Most Common Serious Finding There Is

Last timeTrusting What the Caller Sent

Change one number in a request and get a stranger's invoice. It survives review because the code looks correct: the missing line is a check nobody wrote, and absence is invisible.

The shape of it

A request arrives for an invoice. It carries an identifier. The system is

careful about one thing: the caller is signed in, their session is valid,

their account is active. Satisfied, it fetches the invoice with that

identifier and returns it.

The invoice belongs to somebody else.

That is the whole flaw, and it has a dozen names in a dozen tools. The

single sentence that covers all of them: an identifier arrives from the

caller, the system acts on the record it names, and nothing established

that this caller is entitled to that record. Two different questions were

confused. Who are you was asked and answered. May you have this was never

asked at all.

FIG 1The two questions, and the one that gets skipped
Ten nodes, and the difference between the broken and the fixed system is which of two paths leaves the second gate. The broken path has fewer nodes, which is the honest reason it gets written: it is the shorter program and it passes every test anybody wrote.

Why it is everywhere

Across published assessments this class is reliably at or near the top of

the list, and the reason is not that it is subtle to understand. It is

trivial to understand. The reason is that the defect is invisible to every

process a team normally relies on.

Consider what each process sees. A reviewer reads the function: it parses

an identifier, calls the data layer, formats a response, handles errors.

Every line is correct. There is nothing to object to, because an objection

would have to be about a line that is not there. A test suite exercises

the feature as the feature was described, with one account, and it passes.

A demonstration shows it working. A static analyser looking for dangerous

functions finds none, because no function here is dangerous.

FIG 2What each process would have caught
found by reading the codfound by a scanner, 0 orfound by testing with twrequires knowing what sh
injection into a query1110
a trusted price in the p1100
an unescaped value in a 1100
a dependency with a know1000
a missing entitlement ch0011
a step that trusts an ea0011
The two marked cells are the lesson. The bottom two rows are the only ones a scanner and a reader both miss, because both of those processes look for something wrong and these defects consist of something absent. The third column is the one procedure that finds them, and it costs one extra account.

The consequence is a procedure rather than a principle. You cannot find a

missing check by looking for it. You find it by making a request that

should fail and observing that it succeeds.

The lesson stops here

3 more paragraphs to go

You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.

The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.

See the planThe contents

This is the reading half

Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.

The contents

The rest of this course

  1. 01One Mistake, Wearing Different Clothes
  2. 02The Caller Is Not Running Your Softwareopening only
  3. 03The Most Common Serious Finding There Isyou are here
  4. 04Follow It From the Field to the Place It Runsopening only
  5. 05Your Server Can Reach Things Nobody Outside Canopening only
  6. 06Nobody Chose This, Which Is the Problemopening only
  7. 07Most of What You Ship, You Did Not Writeopening only
  8. 08Could You Reconstruct It Afterwardsopening only

Read alongside