CVE-2026-101028: Ash.count, Ash.exists and Ash.aggregate skip related resources' read policies in filters and sorts
Incorrect Authorization vulnerability in ash-project ash allows an actor to infer data in related records they cannot read via Ash.count/2, Ash.exists/2 and Ash.aggregate/3.
Ash.Actions.Aggregate.run/4 (lib/ash/actions/aggregate.ex) applied only the root resource's read policy before running the aggregate query. The read path also applies each related resource's read policy to filter and sort references that cross a relationship, directly (for example comments.body) or through an aggregate over one, but the aggregate path skipped that step. A caller whose filter or sort reaches these functions, for example through Ash.Query.filterinput/2, an ashlua script, or an AshAi tool offering count or exists results, can test conditions against related rows hidden from them and recover their existence and attribute values one query at a time. Ash.read/2 and its page counts are not affected.
This issue affects ash: from 2.6.0 before 3.34.6.
Affected Software
Event History
Frequently Asked Questions
Which application paths are realistically exposed?
Exposure requires a caller to influence filters or sorts used with Ash.count/2, Ash.exists/2, or Ash.aggregate/3, where those expressions reference related resources. Examples named in the advisory include Ash.Query.filter_input/2, ash_lua scripts, and AshAi tools that provide count or exists results.
What access does an attacker need?
The attacker needs access to an application path that executes the affected aggregate operations and permits conditions on relationship fields or aggregates over relationships. They can use those conditions to test related rows that their actor is not authorized to read, recovering information incrementally.
Are ordinary reads or page counts affected?
No. Ash.read/2 and its page counts are explicitly identified as unaffected.
How can I determine whether my deployment is affected?
Affected versions are ash from 2.6.0 before 3.34.6. A deployment in that range is relevant when it exposes count, exists, or aggregate queries whose caller-controlled filters or sorts can cross relationships.
What can be restricted while an upgrade is pending?
Restrict untrusted access to interfaces that expose Ash.count/2, Ash.exists/2, or Ash.aggregate/3, particularly where users can supply filters or sorts referring to related-resource fields. Review filter-input handlers, ash_lua scripts, and AshAi tools that return count or exists results.