CVE-2026-82681 Overview
CVE-2026-82681 is an Improper Encoding or Escaping of Output vulnerability [CWE-116] in the ash-project/ash_admin library for Elixir. The Table, DataTable, and Show components built row-action URLs through raw string interpolation, splicing primary keys, table names, domain names, and resource names into query strings without URL encoding. Because Ash resources routinely use user-settable string primary keys such as slugs or email addresses, an attacker who controls a record's primary key can inject query parameters that override the intended link target. The issue affects ash_admin from 0.3.0-rc.0 before 1.3.1.
Critical Impact
An admin clicking an edit link on a poisoned row can be silently redirected to a destroy action or an arbitrary resource, enabling unintended data modification or deletion.
Affected Products
- ash-project/ash_admin versions >= 0.3.0-rc.0
- ash-project/ash_admin versions < 1.3.1
- Elixir applications using AshAdmin with user-settable string primary keys (slugs, emails, usernames)
Discovery Timeline
- 2026-08-31 - CVE-2026-82681 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-82681
Vulnerability Analysis
The vulnerability resides in how AshAdmin's row-action components assemble navigation URLs. The Table, DataTable, and Show components concatenated the domain, resource, table, primary_key, and action_type values directly into a query string using Elixir string interpolation. None of the interpolated values were passed through URL encoding.
Ash resources frequently define string primary keys that end users can set, including slugs, email addresses, and usernames. A record whose primary key is stored as foo&action_type=destroy produces a rendered link containing two action_type parameters. Plug.Conn.Query resolves duplicate parameters using last-wins semantics, and because primary_key is interpolated last in the vulnerable templates, the attacker-controlled value overrides the legitimate action_type. A # character in the primary key truncates the remainder of the query string into a URL fragment, achieving a similar override.
The practical result is a stored parameter-injection primitive: an administrator clicking the edit action on a poisoned row can be redirected to a destroy form, or to an entirely different resource or domain.
Root Cause
The root cause is missing output encoding on data used in a URL context, tracked as CWE-116 (Improper Encoding or Escaping of Output). The vulnerable code paths trusted string interpolation to build query strings rather than an encoder that understands application/x-www-form-urlencoded semantics. The fix in commit 8e8ef91 replaces raw interpolation with URI.encode_query/1 via a new admin_path/2 helper, encoding every interpolated value.
Attack Vector
Exploitation requires an attacker to create or update a record whose string primary key contains query-string metacharacters such as &, =, or #. When an authenticated administrator later loads the AshAdmin listing or show page and clicks a row-action link, the browser navigates to the attacker-influenced URL. User interaction from a privileged admin is required to trigger the redirected action.
// Vulnerable pattern (lib/ash_admin/components/resource/show.ex)
<.link
:if={destroy?(@resource)}
- navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=destroy&table=#{@table}&primary_key=#{encode_primary_key(@record)}"}
+ navigate={admin_path(@prefix, domain: AshAdmin.Domain.name(@domain), resource: AshAdmin.Resource.name(@resource), action_type: "destroy", table: @table, primary_key: encode_primary_key(@record))}
>
Destroy
</.link>
<.link
:if={update?(@resource)}
- navigate={"#{@prefix}?domain=#{AshAdmin.Domain.name(@domain)}&resource=#{AshAdmin.Resource.name(@resource)}&action_type=update&table=#{@table}&primary_key=#{encode_primary_key(@record)}"}
+ navigate={admin_path(@prefix, domain: AshAdmin.Domain.name(@domain), resource: AshAdmin.Resource.name(@resource), action_type: "update", table: @table, primary_key: encode_primary_key(@record))}
>
Update
</.link>
// Source: https://github.com/ash-project/ash_admin/commit/8e8ef91e8ba07498053887c6212f8b0f08178df6
Detection Methods for CVE-2026-82681
Indicators of Compromise
- Records with string primary keys containing query-delimiter characters (&, =, #, ?).
- Application logs showing AshAdmin requests where action_type or resource query parameters do not match the link the admin clicked.
- Unexpected destroy or update actions performed by administrators shortly after navigating to a listing page.
Detection Strategies
- Scan the datastore for any resource whose primary key is user-writable and matches the regex [&=#?] to identify potentially poisoned rows.
- Compare Referer and destination action_type values in web server logs to flag mismatches consistent with query-parameter override.
- Review AshAdmin audit trails for administrator-initiated destructive actions preceded by navigation from a list or show view.
Monitoring Recommendations
- Enable structured logging on the AshAdmin /admin route family and forward it to a centralized log store for correlation.
- Alert on high-privilege actions such as action_type=destroy executed within seconds of a GET on a listing page.
- Track version drift of the ash_admin dependency across environments to confirm patched releases are deployed.
How to Mitigate CVE-2026-82681
Immediate Actions Required
- Upgrade ash_admin to version 1.3.1 or later, which rebuilds every row-action link with URI.encode_query/1.
- Audit existing records for primary keys containing &, =, #, or ? and normalize or reject them.
- Restrict AshAdmin access to trusted network locations while patching is in progress.
Patch Information
The fix is available in ash_admin1.3.1 and is implemented in commit 8e8ef91e8ba07498053887c6212f8b0f08178df6. All interpolated URL parameters are now routed through a new admin_path/2 helper that calls URI.encode_query/1. See the GitHub Security Advisory GHSA-j89q-xjrh-c26p and the CNA advisory for CVE-2026-82681 for the official write-up.
Workarounds
- Enforce a resource-level validation that rejects string primary keys containing query metacharacters (&, =, #, ?).
- Prefer integer or UUID primary keys for resources exposed through AshAdmin until the upgrade is complete.
- Temporarily disable destructive row actions (destroy, update) in AshAdmin for resources with user-writable string keys.
# Update the dependency in mix.exs to the patched release
# {:ash_admin, "~> 1.3.1"}
mix deps.update ash_admin
mix deps.get
mix compile
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.