AI News HubLIVE
In-site rewrite4 min read

I source-reviewed 200 self-hosted AI tools for tenant isolation; 78 leaked

A security researcher source-reviewed 200+ multi-tenant AI and SaaS products for cross-tenant data exposure. 78 products had the same flaw: write endpoints had authorization checks, but adjacent read endpoints did not. The post explains the pattern, lists fixed products, and gives advice.

SourceHacker News AIAuthor: dmitry-maranik

Security research

I source-reviewed 200+ self-hosted AI tools for tenant isolation. 78 leaked across tenants.

The same isolation flaw, the un-retrofitted read sibling, in 78 of 200+ multi-tenant AI and SaaS products. The pattern, the fixes that shipped, and how to check your own.

Every team building on top of LLMs eventually ships the same feature: workspaces. Tenants, teams, projects, organizations, whatever you call them, the promise is identical. Your knowledge base, your chat history, your documents, walled off from everyone else on the same instance.

That wall is the one thing a multi-tenant product cannot get wrong. So over the past few months I went looking, systematically, for where it cracks.

I source-reviewed 200+ multi-tenant AI and SaaS products for one specific class of bug, and confirmed cross-tenant data exposure in 78 of them: one tenant able to read (and in some cases modify or delete) another tenant's data. That comes to 84 findings across 78 products, with 31 now filed as GitHub Security Advisories. Almost all of them are the same mistake, and it lives in the read endpoints.

This post explains that mistake, names the ones that are already fixed, and points to the live list of the rest. Everything still unnamed stays that way until its fix ships. I'm not going to hand attackers a live target before users are protected.

How I tested

Two tiers, because 200+ deep labs isn't something one person does, but 200+ source reviews is.

The sweep (200+ products). For each candidate I read the code for one pattern: an authorization check that's enforced on the write path but skipped on a neighboring read. Most products either don't have the bug, aren't actually multi-tenant in their open-source edition, or have already retrofitted every sibling. Those are the majority, and they're the denominator that makes the 78 mean something.

The confirmation (the findings). When the source review flagged a real gap, I confirmed it for real:

Stood up a clean, self-hosted instance (Docker, on my own hardware).

Created two tenants, A and B, with synthetic accounts and synthetic canary data. No real users, no production systems, ever.

Reproduced the cross-tenant read, modify, or delete with Sectum AI, an open-source multi-tenant isolation verifier, and confirmed it against database ground truth.

Captured a signed (RFC-3161-timestamped) evidence pack and reported it privately to the maintainer under coordinated disclosure (90-day hold), usually with the fix attached.

That last step is why the scoreboard below is mostly blank. Most of the 84 findings are still under coordinated disclosure. The maintainers have been told and are shipping fixes, so I name only the ones that are already public and aggregate the rest. The full current list, and each advisory as it publishes, lives at sectum.ai/research.

The pattern: writes are guarded, reads are not

What made the sweep almost mechanical is that the same shape kept repeating. The write path was correctly scoped to the tenant, and the read path right next to it was not.

A developer adds "delete this item" and remembers to check ownership: does this item belong to the caller's tenant? Good. Then someone adds "view this item" or "list its embeddings," and the check never gets copied over. The list/get/search endpoint fetches by a raw ID with no tenant filter. The IDs are often sequential integers or otherwise guessable, so "view item 5" happily returns another tenant's item 5.

I started calling these un-retrofitted read siblings. Once you've seen one, you grep for the rest: find the endpoint that checks ownership, then look at the neighbors that don't. Across 78 products it was the same shape almost every time. This isn't 84 unrelated bugs. It's one bug, 84 times.

There's a second, nastier variant. The check runs, but on the wrong thing. The handler authorizes the path you supplied rather than the object you asked for. You pass your own workspace's ID, which you're allowed to touch, along with a victim's object ID, and the permission check and the object lookup disagree about whose data this is. The two most damaging classes I confirmed were an embedding-vector read (raw RAG vectors, which can partially reconstruct the source text) and a connector re-index that exfiltrates another tenant's content using the victim's own stored OAuth token.

The ones already fixed

Five are public because the maintainers shipped a fix. The teams that moved fastest deserve the credit:

ToolIssue (class)Status

SurfSense Cross-tenant connector re-index to exfiltrate another tenant's GitHub/Notion content using their stored credentials Fixed: PR #1503 merged

AnythingLLM Embed widget exposed to anonymous origins by default Fixed: CVE-2025-63390, PR #5759 merged

Baserow Cross-workspace disclosure of a field's values by serial ID Fixed and deployed: PR #5613

aideepin Cross-user read of another user's RAG chunk text, embedding vectors, and document text by ID Fixed: PR #105 merged

Flagsmith Cross-project read of another project's multivariate-flag values (nested-viewset IDOR); the fix swept four sibling viewsets Fixed: PR #7945 merged

79 more RAG and document leaks, credential-store IDORs, cross-workspace read and tamper, up to Critical severity Under coordinated disclosure, named at sectum.ai/research as fixes ship

Who passed

Plenty of products held. A few are worth naming, because credit is due. Several had clearly audited the whole bug class after a single report, which is the right way to respond.

Isolation held on current releases: Open WebUI, Langfuse, LibreChat, Outline, PraisonAI, Onyx, LangWatch, Khoj. A few had cross-tenant CVEs in older versions; on current releases they're clean.

Not multi-tenant in the open-source edition (no cross-tenant surface to leak): Flowise, Mem0, MaxKB, vLLM. Their workspace isolation is an enterprise feature or an explicitly documented shared-by-design behavior. Worth knowing if you self-host them assuming a wall you don't actually have.

What this means if you're building on AI

Three takeaways, in order of how often they bit.

Authorize reads like you authorize writes. The list/get/search endpoint is not "lower risk" than delete. It's the exfiltration endpoint. When you add an ownership check, grep for every sibling that touches the same object and give them the same check. Better still, enforce tenant scoping at a layer the individual handler can't forget: a query interceptor, a row-level policy, a middleware. Then isolation is the default instead of something each endpoint opts into.

Treat embeddings and cache keys as tenant data. Some of these leaks weren't documents at all. They were RAG vectors and response caches whose keys forgot to include the tenant. If A and B can land in the same cache bucket or read each other's vectors, that is a data leak.

If you self-host, verify the isolation you're assuming. Several popular tools are single-tenant, or shared by design, in their open-source edition. That's a fine design. But if you're putting multiple customers on one instance expecting a wall, check that the wall exists.

On disclosure

Everything here was tested on isolated, self-hosted instances with synthetic accounts and synthetic data. Nothing touched a third-party or production system. Every finding went to the maintainer privately first, with a 90-day hold and an offer to write the fix. The handful named here are public because they're fixed or have an open fix PR. The rest stay unnamed until the people who maintain them have shipped. The full current list is kept up to date at sectum.ai/research, where each advisory appears as it publishes.

If you maintain one of the products still under embargo and want to coordinate timing or a CVE, reach me through sectum.ai/research.

Try it yourself

The checks I ran are open source. Sectum AI stands up two tenants, runs the cross-tenant battery (IDOR/BOLA, RAG entity-bleed, cache contamination, erasure), and emits a signed evidence pack you can hand to an auditor, without having to trust the vendor's word that isolation works. If you're shipping multi-tenant AI, point it at a staging instance before someone else points something less friendly at production.

Explore the open source Full disclosure list Request an assessment

Found and verified with Sectum AI. The full current disclosure list, updated as each advisory publishes, is at sectum.ai/research.