Skip to main content
BlueForge
EngineeringApril 25, 20263 min read

Enforced at the API Layer

Kristian Mandrup

Founder & CEO

In April we audited our own tenancy model and found something worth writing down: eight tables were described, in their own migrations, as "enforced at API layer."

What that phrase means in practice is that the database has no opinion. There is no row-level security, no tenant predicate, no policy — only the hope that every query reaches the database through code that remembers to add WHERE tenant_id = ....

Why it is not a fair defence

"Enforced at the API layer" is not wrong as a design. Plenty of systems are built that way and are careful about it. But it is a claim about every caller, forever, including the ones not written yet — and it fails silently in the direction that hurts.

The tables that made this urgent were not the interesting ones. They were servers and ssh_keys.

What the audit produced

The fix enabled row-level security and added tenant-scoped policies across eleven tables in two databases: the team tables, invitations, servers, SSH keys, the audit log, uptime checks, the auth event log, and the agent action logs. Also a duplicate auth-events table in a second application's database that had drifted along with its copy.

The mechanism that let this happen is mundane: two databases, two migration streams, and a schema that was copied rather than shared. Nothing was hidden. Nobody had asked the question.

The same lesson, the next day

The day after the RLS work, we finished a WebRTC SFU for SocialSphere — designed, scaffolded, and patched in a day — and found an authentication bypass in it. The sequence is worth noting because of the order: an audit, then the bypass the audit found, then the patch. Not a bug report; a deliberate look.

JWT authentication on the signalling path landed before the patch commit, and the patch commit's message is a list rather than a title: "patch critical auth bypass and resource leaks." The room and peer metrics follow-up enforced the secret as a required environment variable, which is the same idea one layer down — a missing secret must stop the service, not quietly change its behaviour.

What we took from it

Two things, and we are still living with both.

The first: a tenancy control that lives in code has an owner, and the owner is a convention rather than a mechanism. When a table holds credentials — SSH keys, server records, tokens — the convention is not enough, because the consequence of a missed predicate is not a confusing page, it is someone else's access.

The second: the phrase itself is the smell. "Enforced at the API layer" is an accurate description of a decision and an inaccurate description of a property. If a control is real, it can be asserted somewhere — a policy, a test, a constraint. If it can only be described in prose, it is a habit.

Four months later

These posts have a thread running through them, and this is where it starts. The four authorization gaps we found in September were the same class of finding, four months on — read paths this time rather than tables, but the same underlying question: not "is the code careful?" but "is there anywhere that knows?"

Stay in the Loop

Get early access to our products and be the first to know when we launch.

Join the Waiting List