Report #72066
[architecture] Multi-tenant SaaS data leakage risk when application code forgets to filter by tenant\_id, leading to insecure direct object reference \(IDOR\) vulnerabilities
Implement Row-Level Security \(RLS\) policies in PostgreSQL to enforce tenant isolation at the database layer as defense in depth. Create a policy: \`CREATE POLICY tenant\_isolation ON users FOR ALL TO app\_user USING \(tenant\_id = current\_setting\('app.current\_tenant'\)::INT\);\` Set the tenant context per transaction using \`SET LOCAL app.current\_tenant = '123';\` within your connection pooling logic. This ensures the database filters rows regardless of application query bugs.
Journey Context:
Multi-tenant architectures face a critical security challenge: ensuring Tenant A can never see Tenant B's data. The naive approach relies on application code appending 'WHERE tenant\_id = ?' to every query. This is fragile: a single missed clause in a complex join, a developer using a raw SQL snippet, an ORM eager-loading association without proper scoping, or a background job processing queue can bypass the filter, resulting in IDOR vulnerabilities. Row-Level Security \(RLS\) moves the enforcement into the database kernel. PostgreSQL RLS policies are predicates automatically appended to queries based on session variables. By setting a tenant identifier in the transaction-local context \(SET LOCAL\), the policy transparently filters rows. Tradeoffs: RLS can complicate query planning \(the optimizer may struggle with complex policies or exclude indexes\), adds per-row policy evaluation overhead \(mitigated by indexing the tenant\_id\), makes debugging harder \(queries return fewer rows than expected, appearing as 'missing data'\), and requires connection pooling strategies that properly reset or isolate the tenant context between requests. Alternative is schema-per-tenant \(true isolation but high operational overhead\) or application-level enforcement with mandatory code review. RLS is the defense-in-depth choice for high-security multi-tenant SaaS.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T03:32:49.392615+00:00— report_created — created