Across the API engagements we ran in the last twelve months, authorisation defects produced more critical findings than every injection class combined. The reason is structural: frameworks give you authentication for free, but authorisation is business logic and nobody can generate it for you.
Why scanners miss it
A scanner cannot know that order 8842 belongs to a different customer. Detecting authorisation failure requires understanding the data model, which means a human or a carefully constructed test harness.
The patterns we find repeatedly
The same four shapes account for most of what we report:
- Identifiers accepted from the request body while the session is ignored
- Read paths protected but export, webhook and reporting paths forgotten
- Admin-only fields accepted on shared update endpoints (mass assignment)
- Second-order access: an object is scoped correctly, its children are not
Fixing it structurally
Point checks decay. The teams that stop shipping these defects centralise authorisation into a policy layer that every data access path must pass through, then write tests that assert denial rather than success.
Denial tests matter: an allow test passing tells you nothing about whether another tenant is also allowed.
Key takeaway
Centralise authorisation, cover asynchronous paths, and write tests that assert access is denied — not just that the happy path works.