CVE-2026-86338 in ash
Summary
by MITRE • 09/16/2026
Ash field_policies are documented to protect against filter-based information disclosure: when a field the actor may not see is referenced in a filter, it is replaced with an expression that evaluates to nil, so a filter cannot be used as a yes/no oracle to read a value the actor cannot see.
This nilling was applied to attributes but not to calculations or aggregates. A user-supplied filter reference to a calculation or aggregate carries an Ash.Query.Calculation / Ash.Query.Aggregate struct, which the authorizer's reference replacement did not match (it only matched the Ash.Resource.* structs), so the filter ran against the real value.
As a result, an actor whose field policies forbid a calculation or aggregate can still filter by it (for example filter(secret_calc == "x") or filter(comment_count == n)) and learn the value from whether rows match — an oracle that recovers field-policy-protected values one probe at a time. Filtering is commonly exposed to lower-privileged actors (for example via AshGraphql or AshJsonApi filter arguments), which is exactly the surface field policies are meant to protect.
The fix routes filter references to calculations and aggregates through the same field-policy nilling as attributes.
This issue affects ash: from 2.11.0-rc.0 before 3.33.4.
If you want to get best quality of vulnerability data, you may have to visit VulDB.
Analysis
by VulDB Data Team • 09/16/2026
A critical information disclosure vulnerability exists within the Ash framework, specifically affecting versions ranging from 2.11.0-rc.0 up to but not including 3.33.4. This flaw stems from an incomplete implementation of field policy enforcement mechanisms designed to prevent filter-based side-channel attacks. In secure systems, access control policies must ensure that unauthorized actors cannot infer the values of restricted fields by observing query results. The Ash framework attempts to mitigate this risk through a mechanism known as nilling, where references to protected fields in user-supplied filters are replaced with expressions evaluating to nil. This ensures that if an actor lacks permission to view a specific field, they cannot use it as a yes-or-no oracle to determine its value by checking whether rows match the filter criteria.
The technical root cause of this vulnerability lies in the scope of the authorization logic responsible for replacing restricted references. The authorizer's reference replacement function was designed to intercept and neutralize only direct attribute references represented by Ash.Resource.* structs. However, it failed to account for more complex query structures such as calculations (Ash.Query.Calculation) and aggregates (Ash.Query.Aggregate). When a user-supplied filter includes a condition based on a calculated field or an aggregate value that is subject to strict field policies, the authorization layer does not recognize these struct types. Consequently, instead of replacing the reference with nil, the system allows the filter to execute against the actual underlying data values.
This oversight creates a significant operational impact by enabling unauthorized information disclosure through side-channel analysis. An actor who explicitly lacks permission to view certain calculated or aggregated fields can still construct queries that filter based on those exact metrics. For instance, an attacker could issue a query with a condition such as filtering for rows where secret_calculation equals a specific value or where comment_count exceeds a threshold. By observing whether any records are returned, the actor effectively uses the database engine as an oracle to deduce sensitive information one probe at a time. This is particularly dangerous because filtering capabilities are frequently exposed through public-facing interfaces like AshGraphql and AshJsonApi filter arguments, which are often accessible by lower-privileged users who rely on these APIs for data retrieval but should not have visibility into restricted metrics.
The vulnerability aligns with CWE-209, which describes the generation of an error message that includes sensitive information, although in this context it manifests as a logical flaw leading to unauthorized data exposure rather than explicit error leakage. It also relates to CWE-613, insufficient session expiration or termination, if we consider the persistent nature of the access control bypass during active sessions. From a threat modeling perspective using MITRE ATT&CK techniques, this behavior facilitates Data from Information Repositories via Indirect Command Execution, where the attacker indirectly extracts data through query result analysis rather than direct retrieval permissions. It also touches upon Privilege Escalation by allowing lower-privileged actors to gain insights reserved for higher-level roles.
To mitigate this risk, developers must upgrade the Ash framework to version 3.33.4 or later, which implements a comprehensive fix that routes filter references to calculations and aggregates through the same field-policy nilling logic applied to standard attributes. This ensures uniform enforcement of access controls across all types of queryable data points. For organizations unable to immediately patch their systems, temporary mitigations involve strictly validating user-supplied filters on the application layer before they reach the database engine. Developers should maintain an allowlist of permitted filter fields and explicitly reject any queries that attempt to reference calculated or aggregated values not included in this list. Additionally, implementing rate limiting on query execution can help mitigate the efficiency of side-channel attacks by increasing the cost for attackers attempting to probe field values through repeated filtering operations.