CVE-2026-77454: exists/2 predicate silently dropped on limited relationships with a parent() filter in AshSql
Incorrect Authorization vulnerability in ash-project ashsql allows a caller to bypass a scoping or authorization filter expressed as exists/2 over a relationship that declares both a limit (or frommany?) and a parent(...)-referencing filter or sort.
AshSql.Join.relatedquery/3 skips the caller-supplied exists predicate for such relationships and delegates it to limitfrommany/5. When the relationship's own filter or sort references parent(...), limitfrommany/5 takes a branch that drops both the limit and the predicate, emitting a bare correlated EXISTS with no predicate. The check then matches any record that has any related row. Most severely, when the expression backs a policy (for example authorizeif expr(exists(memberships, userid == ^actor(:id)))), the actor-scoping condition disappears and the policy passes for any actor with any related row.
This issue affects ashsql: from 0.4.1 before 0.7.1.
Affected Software
Event History
Frequently Asked Questions
Which deployments are exposed to an authorization bypass?
Deployments using ash_sql versions from 0.4.1 before 0.7.1 are affected when an exists/2 expression targets a relationship with a limit (or from_many?) and that relationship has a filter or sort referencing parent(...). The impact is especially severe when that expression is used in an authorization policy.
What must an attacker be able to do for the policy check to pass incorrectly?
The vulnerable policy must use an exists/2 relationship check intended to scope results to the current actor, such as a membership condition comparing user_id to actor(:id). Under the affected relationship conditions, any actor can satisfy the check if the target record has any related row, rather than a related row matching the actor-specific predicate.
Is a default AshSql installation necessarily vulnerable?
No. Exploitation depends on application-defined relationship and policy expressions meeting the affected pattern: a limited relationship plus a parent(...)-referencing relationship filter or sort, queried through exists/2. The provided information does not indicate that this pattern is present by default.
How can teams identify potentially affected policies before updating?
Review exists/2 expressions over relationships that declare a limit or from_many? behavior, then identify relationships whose filter or sort references parent(...). Prioritize expressions used by authorization policies, particularly actor-scoped checks, and determine whether records with any related row could be accessible to actors that do not meet the intended predicate.