Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-82743

CVE-2026-82743: Ash Framework DOS Vulnerability

CVE-2026-82743 is a denial of service flaw in ash-project ash that causes uncontrolled CPU consumption through busy-spinning during asynchronous reads. This post explains its technical details, affected versions, and mitigation steps.

Published:

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.

elixir
   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.
bash
# 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.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.