Report #30479
[architecture] Multi-tenant shared-schema leaks data via missing WHERE clauses
Enable database-level Row-Level Security \(RLS\) with policies that enforce tenant isolation: CREATE POLICY tenant\_isolation ON orders USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::int\); set per-request context via SET app.current\_tenant = '123'.
Journey Context:
Shared-schema multi-tenancy \(single database, tenant\_id column\) is cost-efficient but relies on application queries remembering WHERE tenant\_id = X on every single query. A single missing clause in a complex JOIN or ORM generated query exposes other tenants' data \(security breach\). Schema-per-tenant provides isolation but breaks connection pooling \(requires SET search\_path per request\). PostgreSQL's RLS provides defense-in-depth: the database enforces the tenant filter regardless of application query quality. Policies are enforced for the table owner or specific roles. The application sets the tenant context per request \(e.g., via middleware setting current\_setting\), then queries normally. Even SELECT \* FROM orders returns only rows matching the policy. Tradeoffs: slight performance overhead \(policy check per row\), requires careful index design on tenant\_id, and can block migrations if policy depends on columns being altered.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T05:32:44.807987+00:00— report_created — created