Cross-Tenant Data Leakage

Cross-tenant data leakage occurs when a defect or configuration error allows one tenant to access another tenant’s data. In a Java backend, preventing it requires enforcing tenant isolation at every data-access boundary, not merely filtering results in application code.

In a multi-tenant system, a tenant identifier associates each resource with the organization or customer that owns it. Every request that reads or modifies tenant-scoped data must establish the caller’s tenant context and ensure the requested resource belongs to that tenant.

A common failure occurs when an endpoint accepts a resource ID and queries by that ID alone, such as `SELECT * FROM orders WHERE id = ?`. If IDs are globally addressable, a user who obtains another tenant’s ID may receive that tenant’s record. The safer query includes the tenant boundary, for example `WHERE id = ? AND tenant_id = ?`.

Tenant isolation must also cover writes, updates, deletes, joins, background jobs, caches, search indexes, exports, and administrative APIs. Authentication identifies the caller, while authorization determines whether that caller may access the specific tenant-owned resource.

Defense in depth can include database row-level security, tenant-aware repository methods, foreign keys, scoped ORM queries, and integration tests that deliberately attempt cross-tenant access. The strongest design makes it difficult for individual developers to accidentally issue an unscoped query.

Key points

Interview questions

What is cross-tenant data leakage, and how would you prevent it?

It is a failure of tenant isolation where a user from one tenant can access another tenant’s data. I would derive the tenant identity from trusted authentication context and include it in authorization checks and data queries. For example, a lookup should constrain both the resource ID and `tenant_id`. I would also add tests that attempt to access another tenant’s resources.

Why isn't checking the tenant only in the controller sufficient?

Controllers are only one access path, and other code can reach the same data through jobs, services, scheduled tasks, or additional endpoints. A later layer can accidentally perform an unscoped query even if one controller validates the tenant. Centralizing tenant-aware repository methods reduces this risk. Database-level controls can provide another enforcement layer.

How would you design a Java repository to make cross-tenant queries harder to write accidentally?

I would make tenant context an explicit input to repository operations that access tenant-owned data, or provide a request-scoped tenant context that the repository uses consistently. Repository methods would generate queries containing the tenant predicate rather than accepting arbitrary unscoped queries. I would also review native SQL and bulk operations because ORM-level conventions may not protect them. Integration tests would verify isolation across multiple tenants.

What other components besides the primary database can cause cross-tenant leakage?

Caches are a frequent risk when a key omits tenant identity, because one tenant can receive a cached value created for another. Background processing can also leak data if jobs do not carry the tenant context that existed when they were created. Search indexes, object storage, analytics pipelines, exports, and logs can create similar boundaries. Each component therefore needs an explicit ownership and authorization model.

How would you investigate a suspected cross-tenant data leak?

I would first identify the affected resource, request path, tenant identities, and exact authorization boundary that failed. Then I would trace the data flow through authentication, authorization, repositories, SQL, caches, asynchronous processing, and downstream systems. I would reproduce the issue with two isolated test tenants and preserve relevant audit evidence while avoiding unnecessary exposure of sensitive data. Finally, I would fix the enforcement boundary and add regression tests covering the discovered path and similar paths.