Contact

Security8 min

What an adversarial audit of our own stack found

We told independent reviewers to break our authorisation model. They did.

IRONCLAD is the standing programme that attacks our own systems. It is adversarial by construction: independent reviewers, told to get in, with no obligation to be kind about it. This is a summary of a round of it, including the parts that were our fault.

Finding one: the shared workspace identifier

Our multi-project model gave every project a membership, and every membership a workspace. For an internal team sharing one workspace this is correct behaviour. It also meant the boundary between two projects was thinner than the interface implied — the workspace was the real trust boundary, and the project was presentation.

Nothing leaked to an outside party, because there were no outside parties. But the model would not have survived the first genuinely separate tenant, and the interface was already describing a separation the data layer was not enforcing. We wrote it down as a known limit rather than quietly narrowing the interface language to match.

Finding two: devices could approve themselves

This one was a real defect. A policy intended to let a user read their own device list was written broadly enough to let them update it, and one of the updatable columns was the approval flag. A user could mark their own unapproved device as approved.

It was never exploited and the application never wrote that column from the client — approvals were always issued server-side. But the policy permitted what the application declined to do, which is exactly the gap an attacker operates in. Fixed by dropping the broad policy and re-granting read alone; verified by attempting the update as a non-privileged user and confirming zero rows affected.

The application not doing something is not a control. The database refusing it is a control.

Finding three: a probe that mutated

Not a vulnerability — a process failure, and the most instructive item in the round. While verifying one of the above, a reviewer ran a check that performed an update rather than a read. It affected four rows. It happened to be a no-op because the rows already held the target value, so nothing was damaged.

It could easily have been otherwise. Verification now runs as an unprivileged principal by default, and any probe that writes has to say so and roll back. A check that can change the thing it is checking is not a check.

What is deliberately still open

Publishing findings is only honest if it includes the ones not yet closed. Session tokens live somewhere reachable by client script, which is a real exposure that a server-set cookie would remove. Multi-factor authentication is available and not yet mandatory. Both are scoped, both touch live authentication, and both are being changed carefully rather than quickly.

A hardening programme that only reports successes is a marketing programme. The value of IRONCLAD is that it is allowed to produce bad news, and that the bad news is written down where it can be checked.