CVE-2026-82749 Overview
CVE-2026-82749 is an Incorrect Authorization vulnerability [CWE-863] in the ash-project/ash Elixir framework. The flaw widens a relationship's parent(...) scoping filter to match unintended records when the referenced parent field cannot be resolved. Loading a relationship whose filter references parent(...) resolves that expression against the parent record. When the referenced field is not selected on the source query, the resolution returns nil instead of failing. Scoping predicates such as org_id == parent(org_id) degrade into IS NULL matches, and guards like is_nil(parent(org_id)) or org_id == parent(org_id) activate their unrestricted branch. The relationship then returns records the scope was meant to exclude. The issue affects ash from version 3.13.2 before 3.32.2.
Critical Impact
Authorization scopes silently fail open, exposing tenant or organization data across relationship boundaries when a parent(...) field is not selected on the source query.
Affected Products
- ash-project/ash (Elixir Ash Framework) versions >= 3.13.2 and < 3.32.2
- Applications using relationship filters that reference parent(...) for multi-tenant or organization scoping
- Downstream Ash extensions relying on resolve_parent_in_filter/3 in lib/ash/actions/read/relationships.ex
Discovery Timeline
- 2026-09-01 - CVE-2026-82749 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-82749
Vulnerability Analysis
The vulnerability resides in resolve_parent_in_filter/3 inside lib/ash/actions/read/relationships.ex. Ash relationships can express cross-record scoping using parent(field) expressions, allowing a related query filter to reference an attribute on the parent record. When Ash loads a relationship, it evaluates the filter against the parent record's selected fields. If the referenced parent field is absent from the source query's selection, the resolver previously returned nil rather than raising an error. This behavior turns equality predicates into NULL comparisons at the database layer. A guard clause combining is_nil(parent(org_id)) with an or branch then evaluates the unrestricted arm as true, bypassing the intended row-level scope.
Root Cause
The root cause is a fail-open default in the parent expression resolver. Unresolvable parent(...) references were coerced to nil instead of producing an error tuple. This design choice violated the principle of failing closed for authorization-adjacent logic and allowed silent scope widening [CWE-863].
Attack Vector
Exploitation requires a code path where a developer or extension issues a read whose source query omits the parent attribute referenced by a related filter. The attacker does not need to inject input directly; instead, the attack surface is triggered by legitimate application queries whose selection lists do not include the scoping key. In multi-tenant applications where org_id or tenant_id is the scoping attribute, records belonging to other tenants can be returned to callers whose parent record lacks that attribute in its selection.
if related_query.filter do
resolve_parent_in_filter(related_query.filter, record, relationship.source)
else
- nil
+ {:ok, nil}
end
Source: GitHub Commit e52dad2c
The patch changes the no-filter branch to return {:ok, nil} and, in the broader diff, causes unresolved parent(...) references to fail the read with an error rather than defaulting to nil.
Detection Methods for CVE-2026-82749
Indicators of Compromise
- Application logs showing relationship reads returning records across tenant or organization boundaries.
- Database query logs containing WHERE ... IS NULL predicates in place of expected equality checks on scoping columns such as org_id or tenant_id.
- Ash telemetry events for [:ash, :read] showing successful loads of related records that should have been filtered out.
Detection Strategies
- Perform a code audit for relationship definitions that reference parent(...) in filters and verify the corresponding attribute is included in every source query's select.
- Add integration tests that assert cross-tenant isolation by loading relationships from parent records with minimal field selections.
- Compare produced SQL against expected predicates when loading relationships that use parent(...) scoping.
Monitoring Recommendations
- Enable Ash and Ecto query logging in staging to review generated SQL for unintended IS NULL conditions on scoping columns.
- Instrument application-level authorization checks that re-validate tenant ownership after relationship loads.
- Alert on anomalous row counts returned by read actions that carry parent(...) scoping in their filters.
How to Mitigate CVE-2026-82749
Immediate Actions Required
- Upgrade ash to version 3.32.2 or later, which fails the read when a parent(...) reference cannot be resolved.
- Inventory all resource relationships that use parent(...) in filters and confirm the referenced attributes are always selected on the source query.
- Review recent audit logs for reads that may have returned out-of-scope records prior to patching.
Patch Information
The fix is included in ash3.32.2. The corrective change lives in lib/ash/actions/read/relationships.ex and is tracked in GitHub Commit e52dad2c and GitHub Security Advisory GHSA-j8fx-ff37-4j9c. Additional detail is available in the CNA CVE-2026-82749 Detail and the OSV Vulnerability EEF-CVE-2026-82749 records.
Workarounds
- Explicitly ensure_selected/2 or add the scoping attribute (for example org_id) to every read action that loads a relationship using parent(...).
- Refactor filters to avoid is_nil(parent(field)) or ... disjunctions that expand the result set when the parent field resolves to nil.
- Add policy checks that re-verify tenant ownership on loaded related records until the upgrade is deployed.
# Update the Ash dependency in mix.exs, then fetch and compile
# {:ash, "~> 3.32.2"}
mix deps.update ash
mix deps.get
mix compile --force
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

