CVE-2026-82741
LowCVSS 2.1Exploitation Probability (EPSS)
Low risk3th percentile - higher than 3% of all known CVEs
Summary
Improper validation of specified type of input vulnerability in ash lets an attacker confuse the stored type tag of an Ash.Type.Union value that uses storage: :map_with_tag, bypassing that member's validation and any tag-based authorization. The dump_to_native/2 function did not force the configured tag, allowing a value with a tag naming a different member to be stored.
Risk Assessment
An attacker can bypass validation and authorization, potentially leading to unauthorized data access or integrity issues.
Recommendation
Upgrade the ash library to version 3.32.2 or later to remediate the vulnerability.
Other vulnerabilities in ash
See all- CVE-2026-96581High
The Ash library (ash-project) contains an Authorization Bypass Through User-Controlled Key vulnerability. Under attribute multitenancy, create actions with upsert? true could update another tenant's records and return their attributes, and default upsert fields moved the record into the caller's tenant. The issue affects versions from 1.22.0 before 3.37.2.
- CVE-2026-114214Medium
Incorrect Authorization vulnerability in ash allows a client to read destination records unrelated to the source record through a through relationship. When a has_many relationship with through: is loaded for a single record with a limit of 1, or an unsorted has_one through relationship with a limit of 1, the read path chosen lacks a filter linking destination to source, returning the first destination record by sort or another record with an offset.
- CVE-2026-101028Medium
The ash library (versions from 2.6.0 before 3.34.6) contains an Incorrect Authorization vulnerability that allows an actor to infer data in related records they cannot read via Ash.count/2, Ash.exists/2 and Ash.aggregate/3. The aggregate path applied only the root resource's read policy, skipping related resources' read policies, enabling testing conditions against hidden rows and recovering their existence and attribute values.
- CVE-2026-94201High
Ash stores :atom-typed attributes as strings and compares them as strings. When such an attribute is referenced in a filter, the comparison value is coerced through Ash.Type.Atom. Because the type defined no coerce/2 callback, coercion fell back to the default (cast_input/2), which calls String.to_atom/1 when the attribute is configured with the unsafe_to_atom?: true constraint. Filtering such an attribute with attacker-controlled strings therefore interned a new, permanent atom for every distinct value. Atoms are never garbage collected and the BEAM caps the atom table, so an actor who can supply filter values for a public, filterable :atom attribute declared with unsafe_to_atom?: true can exhaust the atom table and crash the node (denial of service). AshPaperTrail is a notable example: its version resources expose a public, filterable version_action_name atom attribute with unsafe_to_atom?: true by default. The fix adds a coerce/2 to Ash.Type.Atom that never interns atoms — a comparison value is left as a string, since the type is stored and compared as a string. Setting the attribute from action input (cast_input/2, which still honors unsafe_to_atom?) is unchanged. This issue affects ash: from 3.5.1 before 3.34.3.
- CVE-2026-93477Medium
A vulnerability in the Ash library allows a user to set the value of a private action argument on the bulk destroy and bulk update paths. Arguments declared with public?: false should only be set by trusted server-side code, but the lack of a public? check on these paths enables modification from user input.
- CVE-2026-86338Medium
In Ash before version 3.33.4, field policies are documented to protect against filter-based information disclosure, but the nilling was applied only to attributes, not to calculations or aggregates. A user can reference a calculation or aggregate in a filter that they cannot see, and use the filter as an oracle to read the protected value (e.g., filter(secret_calc == "x")).
- CVE-2026-82752Medium
Improper Validation of Specified Quantity in Input vulnerability in ash-project ash allows an attacker to store a value of arbitrary size in an attribute whose length constraint should bound it. Ash measures string length with Elixir's String.length/1, which counts Unicode graphemes, in the max_length and min_length constraints of Ash.Type.String (apply_constraints/2 in lib/ash/type/string.ex), in Ash.Resource.Validation.StringLength, and in the string_length expression function. A grapheme carries an unbounded number of combining marks, so a base character followed by a million combining acute accents is one grapheme and megabytes of data, and satisfies max_length: 2. Where the data layer imposes no independent limit (ETS, Mnesia, or a Postgres text column) the whole value is persisted, so an attacker can write an entire request body into an attribute declared with a small maximum and grow storage without bound. The counting unit also disagrees with the storage layer, which counts codepoints rather than graphemes, so a value accepted by the constraint can still be rejected or truncated by the column. A Postgres varchar(n) column bounds the value itself and is not exposed. This issue affects ash: from 0.10.0 before 3.33.0.
- CVE-2026-82747Medium
Incorrect Authorization vulnerability in ash-project ash returns records that a runtime read policy denies to any actor. When a resource has an access_type :runtime read policy (a check evaluated per record rather than compiled to a filter), Ash.Policy.Authorizer decides each record in check_result/1 by discarding impossible policy scenarios and inspecting what remains. When every scenario for a record was impossible, meaning no policy can authorize it and it must be forbidden, the empty-scenario branch instead kept the record and returned it as authorized. The fix forbids a record whose scenarios are all impossible. This issue affects ash: from 3.4.44 before 3.32.2.
- CVE-2026-82749Medium
In the ash library, an Incorrect Authorization vulnerability widens a relationship's parent(...) scoping filter to match unintended records when the referenced parent field cannot be resolved. The unresolved reference defaults to nil, causing predicates like org_id == parent(org_id) to become IS NULL matches, and guards like is_nil(parent(org_id)) activate unrestricted branches, returning records that should be excluded. The fix fails the read with an error when a parent(...) reference cannot be resolved.
- CVE-2026-82748Low
Incorrect authorization vulnerability in ash authorizes an aggregate under one read action while computing it under another, so an aggregate can run with policies that do not match the action it was authorized against. This can lead to disclosure of information about records the actor cannot read.
Original NVD description (English source)
Improper Validation of Specified Type of Input vulnerability in ash-project ash lets an attacker confuse the stored type tag of an Ash.Type.Union value that uses storage: :map_with_tag, bypassing that member's validation and any tag-based authorization. For a union with storage: :map_with_tag, each member is identified in storage by a configured tag and tag_value. Ash.Type.Union.dump_to_native/2 (lib/ash/type/union.ex) did not force the configured tag when writing the value, so a tag carried in the submitted value was persisted verbatim. An attacker can therefore store a value whose data belongs to one member but whose tag names a different member. On read the value is re-selected by its tag and treated as the incompatible member (a type confusion), bypassing the real member's constraints and any logic or policy that branches on the union tag. The fix drops any incoming tag and forces the configured tag value on dump. This issue affects ash: from 2.14.18 before 3.32.2.
Vulnerability data from NVD (NIST) · CISA KEV · EPSS

