Podcast · Architecture & decisions

The Query That Never Filtered by Company

A brand-new company, zero properties of its own, logged in and saw Camellia's real tenants. What the bug actually was, how it sat unfixed for five months, and the two-step fix that makes it structurally impossible instead of merely repaired.

Companion to the multi-tenant isolation architecture decision — the adversarial audit, tenancy map, and research this episode is built from live there.

The Query That Never Filtered by Company

Deep dive · two hosts · audio pending

What it covers

The mechanism first: five of about twenty record types even carry a field saying which company they belong to, only 27 of 292 data-reading functions take a company id as an input at all, and every check that exists today runs after the data has already been fetched, as an in-memory filter — never as a bound on the database query itself. That is why a company with zero properties of its own could see another company's real tenants, revenue, and conversations on seven pages.

How it was found: not by accident, but by building a genuinely non-staff test login specifically because every prior walkthrough had used a PropFlow staff address — and staff are supposed to see everything, so a broken page and a working page looked identical from the inside.

How it got in: a gap named correctly, in writing, on May 4 — then partially closed, then explicitly deferred on July 30 with a reason but no owner and no date, then invisible for five months because until September 1 there was effectively one customer, so there was nothing to leak between companies.

What real multi-tenant systems do about this — silo, pool, and bridge; AWS's per-request LeadingKeys credential and its one documented hole; Postgres row-level security; and the code-discipline middle path — and the two-step decision on the table: make forgetting impossible first, then make the database itself refuse, even if the code has a bug.

Before you quote anything from this

This is a product-bug writeup, not a security disclosure. No customer was attacked and no credentials were stolen — a query fetched the wrong rows. No real external customer has ever actually been exposed: every time this bug was observed, it was a deliberate, staff-run test account. The audio is a NotebookLM Audio Overview generated from the source doc and outline below, and the transcript (once it exists) is machine-made from that recording — proper nouns get fixed by hand before anything is quoted, per ARTIFACT-STYLE.md.

Chapters

  1. The Login That Saw Someone Else's Tenants
  2. Not a Break-In — a Query That Never Filtered by Company
  3. How You Test for a Wall You're Allowed to Walk Through
  4. The Chain of Numbers: 5, 27 of 292, 662, 12 of 25
  5. May 4: The Gap Was Named on Day One
  6. “Held, Deliberately” Is Not a Complete Sentence
  7. Why One Customer Hides a Multi-Customer Bug
  8. Silo, Pool, and Bridge: How Everyone Else Does This
  9. The Key That Physically Can't Open the Wrong Door — and the One Thing It Can't Cover
  10. Two Steps, Not One: Make Forgetting Impossible, Then Make the Database Refuse
  11. What Got Rejected, and Why It Was the Right Call
  12. The Rule Until Step One Ships
  13. What Proof Actually Looks Like

Chapter list is the outline's suggested chapters (see the Outline tab). It becomes a real, clickable chapter list off the audio's own cue points once the recording exists.

PropFlow Docs