CVE-2026-82743 Overview
CVE-2026-82743 is an uncontrolled resource consumption vulnerability [CWE-400] in the ash-project/ash Elixir framework. The flaw resides in Ash.Actions.Read.AsyncLimiter.await_at_least_one/1, which polls concurrent async read tasks with Task.yield(task, 0) in a tight loop instead of blocking. While any outstanding task is still running, the loop returns immediately and repeats, pinning a BEAM scheduler thread at full CPU for the entire duration of the slow read. Concurrent slow reads tie up additional schedulers, degrading application throughput. The issue affects ash from version 2.19.0 up to but not including 3.32.2.
Critical Impact
A slow related-data load or calculation causes a BEAM scheduler thread to busy-spin at 100% CPU, and concurrent slow reads can exhaust multiple schedulers.
Affected Products
- ash-project/ash versions >= 2.19.0 and < 3.32.2
- Elixir applications relying on Ash.Actions.Read async execution paths
- Downstream Ash extensions performing related-data loads or calculations under async reads
Discovery Timeline
- 2026-09-01 - CVE-2026-82743 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-82743
Vulnerability Analysis
The defect is a busy-wait loop in the async read limiter. await_at_least_one/1 iterates over the list of in-flight Task structs and calls Task.yield(task, 0) on each. A zero timeout returns nil immediately when a task has not completed, so when every outstanding task is still running the enclosing loop makes no progress and repeats without yielding to the scheduler. The BEAM runtime treats this as CPU-bound work and dedicates a scheduler thread to it for the entire lifetime of the slow read. When several Ash reads run concurrently, each spinning limiter consumes another scheduler, shrinking the pool of threads available for other processes on the node.
Root Cause
The root cause is incorrect use of a non-blocking polling primitive in place of a blocking wait. Task.yield/2 with a 0 timeout is a probe, not a synchronization point. The fixed code uses Task.yield_many/2: a non-blocking sweep with timeout: 0 collects any already-completed tasks, and when none have completed it falls back to Task.yield_many(pending, limit: 1, timeout: :infinity), which blocks the process until at least one task finishes. The process now sleeps instead of spinning.
Attack Vector
Exploitation requires a local, low-privilege actor able to trigger an Ash read whose related-data load or calculation is slow. No authentication or user interaction is required by the framework itself, but the attacker must be able to invoke a read action against a resource that performs asynchronous work. Any slow read is sufficient; the impact scales with the number of concurrent slow reads and can starve unrelated BEAM processes on the same node.
def await_at_least_one([]), do: {[], []}
def await_at_least_one(list) do
- list
- |> Enum.map(fn
- %Task{} = task ->
- case Task.yield(task, 0) do
- {:ok, {:__exception__, e, stacktrace}} ->
- reraise e, stacktrace
+ {non_tasks, tasks} = Enum.split_with(list, &(!match?(%Task{}, &1)))
+
+ case tasks do
+ [] ->
+ {non_tasks, []}
- {:ok, term} ->
- term
+ tasks ->
+ {complete, pending} = collect_yielded(Task.yield_many(tasks, timeout: 0))
- {:exit, term} ->
- {:error, term}
+ case non_tasks ++ complete do
+ [] ->
+ collect_yielded(Task.yield_many(pending, limit: 1, timeout: :infinity))
- nil ->
- task
+ complete ->
+ {complete, pending}
Source: GitHub commit 0a5ecd2 — patch to lib/ash/actions/read/async_limiter.ex replacing the busy-poll loop with a blocking Task.yield_many wait.
Detection Methods for CVE-2026-82743
Indicators of Compromise
- Sustained 100% CPU utilization on one or more BEAM scheduler threads correlated with active Ash read actions.
- Elixir Observer or :scheduler telemetry showing scheduler utilization near 1.0 while application throughput stalls.
- Latency spikes on unrelated GenServers and processes co-located on the same BEAM node during slow Ash reads.
Detection Strategies
- Inventory Elixir applications and identify any dependency on ash between 2.19.0 and 3.32.2 using mix deps or lockfile scans.
- Instrument Ash read actions with :telemetry and flag reads whose duration exceeds an expected threshold while scheduler utilization climbs.
- Compare scheduler wall-clock time against reductions to spot busy-wait patterns characteristic of tight polling loops.
Monitoring Recommendations
- Export BEAM scheduler utilization and run-queue length to your metrics backend and alert on prolonged saturation.
- Track p95 and p99 latency for Ash read actions and correlate spikes with CPU saturation events.
- Log related-data loads and calculations that exceed a configurable duration so operators can identify triggering resources.
How to Mitigate CVE-2026-82743
Immediate Actions Required
- Upgrade ash to version 3.32.2 or later in all affected applications.
- Audit resource read actions for slow related-data loads and calculations that could serve as trigger conditions.
- Apply rate limiting or timeouts at the application layer for read actions exposed to untrusted callers.
Patch Information
The fix is committed in 0a5ecd2ffdfa848afdeb8827f02982ef2a63a1cd and released in ash3.32.2. It rewrites Ash.Actions.Read.AsyncLimiter.await_at_least_one/1 to use Task.yield_many/2 with timeout: :infinity, so the calling process sleeps until at least one task completes. See the GitHub Security Advisory GHSA-33wq-x3q2-c92h and the CNA advisory for CVE-2026-82743 for full details.
Workarounds
- Set explicit timeouts on Ash read actions to bound the duration of any single busy-wait cycle.
- Reduce concurrency of async reads until the upgrade is deployed to limit scheduler exhaustion.
- Move slow related-data loads and calculations to synchronous or externally queued execution paths where feasible.
# Update dependency in mix.exs to the patched version
# {:ash, "~> 3.32.2"}
mix deps.update ash
mix deps.get
mix compile
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

