CVE-2026-70395 Overview
CVE-2026-70395 is an Improper Neutralization of Special Elements in Data Query Logic vulnerability [CWE-943] in the ash-project/ash framework for Elixir. The flaw allows an attacker to forge a relationship to a record they cannot name and to recover the secret value used to look it up. The issue affects ash from version 1.52.0-rc.11 before 3.31.1. The vulnerability arises when manage_relationship is used with on_lookup: :relate on a belongs_to relationship, enabling client-supplied nested maps to be interpreted as filter predicates.
Critical Impact
An attacker can transform a lookup for a specific record into a boolean oracle, progressively recovering secret lookup values without authorization bypass.
Affected Products
- ash-project ash versions 1.52.0-rc.11 through 3.31.0
- Elixir applications using manage_relationship with on_lookup: :relate on belongs_to relationships
- Applications relying on Ash.read_one/2 for relationship lookups without explicit type casting
Discovery Timeline
- 2026-08-09 - CVE-2026-70395 published to NVD
- 2026-08-12 - Last updated in NVD database
Technical Details for CVE-2026-70395
Vulnerability Analysis
The vulnerability resides in how ash processes client-supplied lookup values inside manage_relationship when on_lookup: :relate is configured on a belongs_to relationship. The client-supplied lookup value is passed directly to Ash.Query.filter/2 without being cast to the attribute type. This allows a nested map submitted where a scalar is expected to be interpreted as a filter predicate rather than a literal value.
A lookup intended to resolve a specific record therefore becomes a broader query for any record matching an attacker-controlled condition. The same code path omits Ash.Query.limit(1), so Ash.read_one/2 can distinguish between no match, one match, and several matches. This distinction turns comparison predicates into an oracle that leaks information about the secret lookup value.
Authorization is unaffected. The destination read policy still applies, which limits the impact to records the caller is permitted to read.
Root Cause
The root cause is missing type casting on the client-supplied lookup input before it reaches Ash.Query.filter/2. Combined with the absence of Ash.Query.limit(1), the query result cardinality itself becomes a side channel for the attacker.
Attack Vector
An attacker submits a nested map containing comparison operators in place of the scalar lookup value. By observing whether Ash.read_one/2 returns no result, one result, or an ambiguity error, the attacker performs a binary-search style recovery of the target secret. The attack is local in scope but requires no privileges beyond normal client interaction with the relationship endpoint.
The vulnerability mechanism is described in the GitHub Security Advisory GHSA-vvp6-3wv6-833j and the CNA advisory for CVE-2026-70395.
Detection Methods for CVE-2026-70395
Indicators of Compromise
- Repeated requests to relationship endpoints where the lookup field contains nested JSON objects or map structures instead of scalar values
- Sequential requests to the same relationship endpoint that vary comparison operators such as gt, lt, or eq in the payload
- Application log entries showing Ash.read_one/2 errors indicating multiple matching records where a single record was expected
Detection Strategies
- Inspect application logs for manage_relationship invocations that produce ambiguous read errors from Ash.read_one/2
- Alert on inbound request bodies where a field bound to a belongs_to lookup contains a map structure rather than a primitive value
- Correlate high-frequency lookup requests from a single client against the same relationship parameter to identify oracle-style enumeration
Monitoring Recommendations
- Enable request-body logging for endpoints using Ash resources with manage_relationship and on_lookup: :relate
- Track query cardinality anomalies where lookup queries return more than one record
- Review the fix commit at ash-project/ash commit 09f42593 to build detection rules matching pre-patch code paths
How to Mitigate CVE-2026-70395
Immediate Actions Required
- Upgrade ash to version 3.31.1 or later across all affected Elixir applications
- Audit resource definitions for manage_relationship calls that use on_lookup: :relate on belongs_to relationships
- Validate and reject client input where scalar lookup fields receive map or nested structures
Patch Information
The fix is available in ash3.31.1. The patch enforces type casting on lookup values and constrains the read to a single record. See the remediation commit and the OSV vulnerability report EEF-CVE-2026-70395 for full remediation details.
Workarounds
- Add explicit input validation at the controller or context layer to reject non-scalar values for lookup fields
- Replace on_lookup: :relate flows with manual lookup logic that casts input and calls Ash.Query.limit(1) explicitly
- Restrict access to endpoints exposing manage_relationship behavior until the upgrade is deployed
# Update ash dependency in mix.exs to the patched version
# {:ash, "~> 3.31.1"}
mix deps.update ash
mix deps.get
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

