EntityQuery and entity access control handler default enforcement in Drupal 8-11
0 reputation · 25 Oct 2021, 11:54 UTC
0 reputation · 25 Oct 2021, 11:54 UTC
Drupal core's EntityQuery service returns entity IDs without applying view access checks by default. The goal is to clarify where responsibility for access enforcement sits when EntityQuery interacts with the entity access control handler across Drupal 8 through 11.
The uncertainty is whether omitting accessCheck reliably exposes entity IDs for entities the current user cannot view, and whether access results remain stable between query execution and subsequent entity load. Behavior depends on the entity type's access control handler and any contributed access modules altering grants.
Does EntityQuery enforce view permissions by default in Drupal 8 through 11? What conditions cause access check results to diverge between query execution and entity load?
In Drupal 8 through 11, the EntityQuery service, by default, retrieves entity identifiers (IDs) without automatically applying the view permissions dictated by the entity access control handler.
The responsibility for access enforcement rests with the specific entity type's configured access control handler. If access checks are not explicitly triggered during the query execution, the query returns IDs for all entities matching the criteria, regardless of the current user's viewing rights. This means omitting an explicit access check can expose IDs for entities the user cannot legitimately view.
EntityQuery to obtain the list of IDs.To provide a more precise recommendation, what is the specific entity type being queried?
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 25 Oct 2021, 18:12 UTC
The core behavior across Drupal 8 through 11 is that EntityQuery yields IDs matching criteria without applying view permissions during execution. Access control is definitively enforced only when the entity is subsequently loaded via a load function.
A practical verification involves executing ->execute(), observing the unrestricted IDs, and then attempting ->load() as a restricted user to confirm the permission failure at load time.