CVE-2026-82744 Overview
CVE-2026-82744 is a fail-open vulnerability in the ash-project/ash Elixir library. The flaw resides in Ash.Reactor.ChangeStep (lib/ash/reactor/steps/change_step.ex), where guard evaluation logic conflated raised exceptions with unmet conditions. When a where validation guarding a reactor change raises an exception, the step is bypassed rather than halted. Security-relevant changes that should enforce a modification can be silently skipped when attacker-influenced input triggers a guard exception. This weakness is categorized under [CWE-636: Not Failing Securely (Failing Open)]. The issue affects ash from version 3.0.0-rc.17 up to but not including 3.32.2.
Critical Impact
A raised exception inside a where guard causes a security-enforcing Ash.Reactor change to be skipped instead of halting the workflow, potentially allowing unauthorized state transitions.
Affected Products
- ash-project/ash version 3.0.0-rc.17 and later
- ash-project/ash versions prior to 3.32.2
- Elixir applications using Ash.Reactor.ChangeStep with where clause guards
Discovery Timeline
- 2026-09-01 - CVE-2026-82744 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-82744
Vulnerability Analysis
The Ash framework provides Ash.Reactor workflows where each change step can be gated by where validations. These validations act as guards that decide whether a change executes. The vulnerable code in lib/ash/reactor/steps/change_step.ex evaluated guards inside apply_where_clauses/3, delegating to apply_validation.
The function apply_validation rescued any raised exception and returned it as {:error, error}. The surrounding Enum.reduce_while treated this identical to a legitimate {:error, _} result meaning the guard condition was not met, and it bypassed the change with a {:bypass, changeset} value.
The practical outcome is a business logic failure: a change designed to enforce a security-relevant modification is silently skipped whenever its guard raises. This is a fail-open condition rather than a fail-closed one.
Root Cause
The root cause is conflation of two distinct control-flow outcomes. A guard returning {:error, _} legitimately means the condition was not met, so the change should be skipped. A guard raising an exception means the guard could not be evaluated at all, and the correct behavior is to halt. The rescue clause in apply_validation collapsed both into {:error, error}, removing the distinction the reducer needed.
Attack Vector
An attacker who can influence input consumed by a where guard can craft data that causes the guard to raise. Because the reactor step then bypasses the guarded change, any security-enforcing transformation, such as scoping a resource, tagging ownership, or applying an authorization-relevant attribute, is omitted. The attack requires local access to a workflow entry point that feeds attacker-controlled data into a guard.
# Patch: lib/ash/reactor/steps/change_step.ex
# Distinguishes raised exceptions from unmet conditions, failing closed.
Enum.reduce_while(clauses, {:ok, changeset}, fn clause, {:ok, changeset} ->
case apply_validation(changeset, clause, context) do
:ok -> {:cont, {:ok, changeset}}
+ {:raised, error} -> {:halt, {:error, error}}
{:error, _} -> {:halt, {:bypass, changeset}}
end
end)
Source: GitHub commit 6d2eb86. The fix introduces a new {:raised, error} return value and halts the reactor with {:error, error} when a guard raises.
Detection Methods for CVE-2026-82744
Indicators of Compromise
- Application logs showing rescued exceptions inside Ash.Reactor.ChangeStepapply_where_clauses/3 prior to patching
- Resource records missing expected attributes normally set by a guarded Ash.Reactor change
- Unexpected {:bypass, changeset} outcomes in reactor telemetry for changes that should have executed
Detection Strategies
- Inventory Elixir dependencies with mix deps and identify projects pinning ash between 3.0.0-rc.17 and versions below 3.32.2
- Review Ash.Reactor definitions for change steps gated by where clauses that consume external or user-supplied input
- Add telemetry around Ash.Reactor.ChangeStep to record every guard exception and bypass decision for later audit
Monitoring Recommendations
- Alert on any exception raised within a where guard evaluation, correlating the input source and the reactor step name
- Track counts of bypassed change steps per resource and investigate statistical anomalies
- Ingest Elixir application telemetry into a centralized logging pipeline to enable historical review of guard behavior
How to Mitigate CVE-2026-82744
Immediate Actions Required
- Upgrade ash to version 3.32.2 or later across all applications and CI build pipelines
- Audit every Ash.Reactor change gated by a where clause for guards that could raise on hostile input
- Add input validation upstream of reactor workflows so guards receive well-formed data
Patch Information
The fix is delivered in ash version 3.32.2. It changes apply_validation to return {:raised, error} when a guard raises and updates the reducer in apply_where_clauses/3 to halt with {:error, error} on that value. See the GitHub Security Advisory GHSA-3xq4-m876-fr88 and the CNA CVE-2026-82744 Record for full details.
Workarounds
- Wrap sensitive guard logic in defensive functions that return {:error, reason} explicitly instead of allowing raises
- Add explicit validations after any guarded change to reassert required post-conditions and abort the workflow if they fail
- Restrict the reactor entry points to trusted callers until the upgrade to 3.32.2 is complete
# Update the Ash dependency in mix.exs
# {:ash, "~> 3.32.2"}
mix deps.update ash
mix deps.get
mix compile --warnings-as-errors
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

