CVE-2026-81853 Overview
CVE-2026-81853 is an authorization bypass through user-controlled key vulnerability [CWE-639] in the ash_admin package for the Ash framework in Elixir. The flaw resides in AshAdmin.Helpers.decode_primary_key/2, which decodes a Base64-plus-Erlang-Term-Format (ETF) composite primary key from a URL and passes the resulting map directly into the record-lookup filter. Because the decoder never verifies that decoded keys correspond to the resource's primary-key fields, an attacker can transform the lookup URL into an equality oracle for sensitive attributes such as API tokens or password reset tokens. The issue affects ash_admin from 0.1.0 before 1.3.1.
Critical Impact
An authenticated low-privilege user can brute-force sensitive attribute values one equality guess at a time by encoding attacker-controlled field names into the composite primary-key parameter.
Affected Products
- ash_admin versions 0.1.0 through 1.3.0 (Elixir/Ash framework administrative UI)
- Applications embedding ash_admin that expose resources with sensitive non-primary-key attributes
- Ash resources using composite primary keys reachable via ash_admin lookup routes
Discovery Timeline
- 2026-08-31 - CVE-2026-81853 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-81853
Vulnerability Analysis
The vulnerable helper AshAdmin.Helpers.decode_primary_key/2 reconstructs a composite primary key from a Base64-encoded ETF payload embedded in the URL. After Base64 decoding and a size check, it calls Ash.Helpers.non_executable_binary_to_term/2 with the :safe option to deserialize the payload into an Elixir map. The decoded map is then returned as the filter expression used to locate the record, without validating that the map's keys are actual primary-key fields.
While the :safe deserialization guard rejects new atoms, funs, and nested expressions, it still permits any already-interned attribute name. Because Ash resources typically intern all their attribute atoms at compile time, an attacker can inject keys such as :api_token or :reset_token into the filter. Map.to_list/1 accepts structs as well as maps, allowing an attacker to smuggle a __struct__ key into the decoded output.
Root Cause
The root cause is missing key allow-listing during deserialization. The decoder trusts the shape of the client-supplied ETF payload and treats every decoded key as a legitimate filter field. Filtering by an arbitrary attribute converts a record-lookup route into an equality oracle: a successful lookup confirms the guessed value, while a miss returns a not-found response.
Attack Vector
An attacker with access to the admin interface encodes a map such as %{api_token: "guess"} using ETF, Base64-encodes the result, and submits it as the composite primary-key parameter. The server splices the map into an Ash filter and returns a hit or miss, enabling one-guess-at-a-time brute forcing of sensitive attribute values. Because the check operates over equality rather than substring match, feasible targets are values with limited entropy or previously leaked partial secrets.
with {:ok, decoded} <- Base.decode64(string),
:ok <- check_primary_key_size(decoded, max_byte_size),
term <- Ash.Helpers.non_executable_binary_to_term(decoded, [:safe]),
- :ok <- check_no_expression(term) do
+ :ok <- check_no_expression(term),
+ :ok <- check_primary_key_fields(term, pkey) do
{:ok, Map.to_list(term)}
else
_ -> :error
Source: GitHub commit 3c3e905. The patch adds check_primary_key_fields/2, which rejects any decoded key that is not a declared primary-key field of the target resource.
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-81853
Indicators of Compromise
- Repeated requests to ash_admin record-lookup routes with distinct Base64-encoded composite-primary-key parameters from the same session or IP.
- High-volume 404 or not-found responses from admin lookup endpoints followed by a successful 200 on a similar URL, indicating a successful equality guess.
- Decoded ETF payloads containing map keys that do not match the resource's declared primary-key fields, including __struct__.
Detection Strategies
- Log the decoded key names from every decode_primary_key/2 invocation and alert when they diverge from the resource's primary-key schema.
- Instrument ash_admin routes with rate limits and anomaly detection on repeated near-identical requests differing only in the primary-key parameter.
- Review web access logs for enumeration patterns against ash_admin show or edit routes.
Monitoring Recommendations
- Ingest Phoenix and ash_admin application logs into a centralized log platform and build detections for lookup-parameter fuzzing.
- Monitor authentication and token-reset flows for anomalous usage that could indicate a token discovered via oracle attack.
- Track deployed ash_admin versions across environments to confirm every instance is running 1.3.1 or later.
How to Mitigate CVE-2026-81853
Immediate Actions Required
- Upgrade ash_admin to version 1.3.1 or later in every affected project and redeploy.
- Rotate any long-lived secrets stored on Ash resources exposed through ash_admin, including API tokens and password reset tokens.
- Restrict access to ash_admin routes to trusted networks or authenticated administrators until patching is complete.
Patch Information
The fix is delivered in ash_admin1.3.1 via commit 3c3e905d47f1155dcc1ca3fb347348b05a66065a. It introduces check_primary_key_fields/2, which validates that every decoded key matches a declared primary-key field before the map is used as a filter. See the GitHub Security Advisory GHSA-jxr8-hpv2-qp38 and the CNA advisory for full details.
Workarounds
- Place ash_admin behind an authenticated reverse proxy or VPN to limit exposure to trusted operators.
- Temporarily disable ash_admin routes for resources containing sensitive non-primary-key attributes such as tokens or secrets.
- Add a plug that rejects requests whose decoded composite primary key contains keys outside the resource's primary-key schema.
# Update the ash_admin dependency in mix.exs and fetch the patched release
# mix.exs
# {:ash_admin, "~> 1.3.1"}
mix deps.update ash_admin
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.

