Report #42264
[architecture] Row Level Security policies bypassed or tenant data leaks between requests when using PgBouncer or RDS Proxy
Use SET LOCAL \(transaction-scoped\) configuration for the tenant ID instead of SET SESSION, or use security definer functions that validate tenant context passed as arguments, never relying on session state that survives connection reuse.
Journey Context:
PostgreSQL Row Level Security \(RLS\) is powerful for multi-tenancy, but it relies on session-level configuration variables \(current\_setting\('app.current\_tenant'\)\) to determine which rows to expose. When using external connection poolers \(PgBouncer in transaction mode, RDS Proxy\), connections are reused across different HTTP requests and tenants. If you use SET SESSION, the tenant ID persists into the next request using that connection, causing catastrophic data leakage. The fix is SET LOCAL, which scopes the variable to the current transaction, ensuring cleanup on COMMIT/ROLLBACK. However, SET LOCAL requires that the application ensures every transaction sets the tenant ID. An alternative is avoiding session state entirely: pass tenant\_id as an argument to security definer functions or use column-level checks in queries. Pro tip: Always test RLS policies with connection pooling enabled in your test suite.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T01:24:38.802930+00:00— report_created — created