You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Description: searchObjectsPaginated is called with _multitenancy: false throughout handleIndex and handleShow. Additionally, getTenantStatus fails open on exception (returns a permissive default rather than throwing). The result is that non-superuser consumers can read records belonging to other tenants/organisations when the tenant resolution encounters any error condition.
In a multi-municipality deployment (the typical procest scenario) this means one municipality's medewerkers can read another municipality's zaak records, including BSN, names, and case history.
Scenario:
Municipality A and Municipality B both use the same procest instance.
A medewerker from Municipality A's consumer makes a GET /api/zrc/zaken request.
getTenantStatus throws an exception (e.g., a transient DB error or misconfigured tenant config).
The fail-open handler returns a permissive default.
searchObjectsPaginated runs with no tenant filter — Municipality B's zaken are included in the response.
Suggested fix:
Pass an organisation = <consumer.tenant> filter to searchObjectsPaginated for all non-superuser consumers.
Change getTenantStatus to fail-closed: on exception, throw or return a state that causes a 503 rather than proceeding without a tenant constraint.
Add an integration test that verifies cross-tenant records are never returned to a non-superuser consumer.
Severity: HIGH
Location:
lib/Service/ZgwService.php:901-904Description:
searchObjectsPaginatedis called with_multitenancy: falsethroughouthandleIndexandhandleShow. Additionally,getTenantStatusfails open on exception (returns a permissive default rather than throwing). The result is that non-superuser consumers can read records belonging to other tenants/organisations when the tenant resolution encounters any error condition.In a multi-municipality deployment (the typical procest scenario) this means one municipality's medewerkers can read another municipality's zaak records, including BSN, names, and case history.
Scenario:
GET /api/zrc/zakenrequest.getTenantStatusthrows an exception (e.g., a transient DB error or misconfigured tenant config).searchObjectsPaginatedruns with no tenant filter — Municipality B's zaken are included in the response.Suggested fix:
organisation = <consumer.tenant>filter tosearchObjectsPaginatedfor all non-superuser consumers.getTenantStatusto fail-closed: on exception, throw or return a state that causes a 503 rather than proceeding without a tenant constraint.Source: deep team-reviewer pass 2026-05-27