Skip to main content
All insights

Why security debt accumulates quietly

An application with an unreviewed access model looks exactly like one with a sound access model. That is the whole problem.

5 min read

Nothing fails loudly

A functional bug announces itself. A page breaks, a total is wrong, a customer calls. There is a feedback loop, and the loop closes quickly.

An access-control gap has no such loop. The application serves pages, accepts submissions and sends email exactly as it would if the model were correct. The difference between the two only becomes visible when somebody deliberately looks — or when somebody else does.

This is why security debt behaves differently from technical debt. Technical debt slows you down, which is a signal. Security debt costs nothing at all until it costs a great deal.

The defaults were reasonable at the time

The findings we see are rarely careless. They are usually defaults that made sense during early development and were never revisited: a database role opened up so the prototype could read its own data, a session check that trusts the presence of a cookie rather than its contents, endpoints that appear to sit behind a gate because their sibling pages do.

Each of those is a sensible decision at the moment it is made. What is missing is the later moment where someone asks whether it is still true.

Reading code is not testing behaviour

Code review tells you what the author intended. It does not tell you what the deployed system does. Those diverge more often than most teams expect, particularly where a framework, a hosting platform and a database each apply their own defaults.

The practical answer is to assert behaviour against the running system: call the endpoint without a session and confirm the denial, attempt the write with a forged token and confirm it fails, query the database with the public key and confirm nothing comes back. Assertions like these either hold or they do not — there is no interpretation involved.

What to do about it

Treat independent validation as a scheduled activity rather than a reaction. It does not need to be large: a focused assessment of the access model, the data surface and the secrets handling will find most of what matters.

And when something is fixed, prove it. A fix asserted from a code diff is a hypothesis. A fix demonstrated against production is a result.

Want to talk this through against your own systems?

Describe the situation and we will tell you honestly whether there is work worth doing, and where it should start.