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

CVE-2026-82579: ash_ai Infinite Loop DOS Vulnerability

CVE-2026-82579 is a denial of service vulnerability in ash_ai that allows attackers to trigger infinite loops through manipulated tool calls. This article covers the technical details, affected versions, and mitigation strategies.

Published:

CVE-2026-82579 Overview

CVE-2026-82579 is an infinite loop vulnerability [CWE-835] in the ash_ai library for the Elixir Ash framework. The flaw resides in AshAi.ToolLoop, which drives model-tool interactions for large language model (LLM) agents. An attacker who can influence a model's output, such as through prompt injection, can force the tool loop to hang and issue unbounded, repeated model requests. The issue affects ash_ai from version 0.6.0 before 1.0.0.

Critical Impact

Prompt-injected content can drive unlimited model calls, exhausting API quotas and compute budgets while stalling agent execution when max_iterations: :infinity is configured.

Affected Products

  • ash-project/ash_ai versions 0.6.0 through < 1.0.0
  • Elixir Ash framework applications integrating AshAi.ToolLoop
  • LLM-backed services using ReqLLM.StreamResponse classification through ash_ai

Discovery Timeline

  • 2026-08-31 - CVE-2026-82579 published to NVD
  • 2026-09-01 - Last updated in NVD database

Technical Details for CVE-2026-82579

Vulnerability Analysis

The vulnerability lives in the tool-call handling path of AshAi.ToolLoop. When a model response is classified as :tool_calls, ash_ai passes the calls through normalize_tool_calls/2 and unprocessed_tool_calls/2. Both filters can return an empty list. A call missing a valid tool name is dropped by normalization. A call reusing a tool_call_id that already has a result stored in conversation history is dropped as already processed.

When the filtered list is empty, the loop appends nothing to the message history and recurses with a byte-identical message list. The conversation state never advances. The same model request is re-sent on every iteration. Under the supported setting max_iterations: :infinity, the loop never terminates. With a finite budget, it consumes the entire iteration allowance while producing no progress.

Root Cause

The root cause is a missing terminal condition after tool-call filtering. The original code checked whether classification.type == :tool_calls, but did not check whether any calls survived normalization and deduplication. Because prompt-injected model output can deliberately re-emit a spent tool_call_id, an attacker can steer the model into producing responses that always filter to an empty list, keeping the loop stuck.

Attack Vector

Exploitation requires the ability to influence model output. In practice, this means indirect prompt injection through untrusted data ingested by the agent, such as retrieved documents, tool results, or user-supplied context. The attacker crafts content that causes the model to emit tool calls with reused tool_call_id values or invalid names. Every iteration then filters to an empty list, and ash_ai re-sends the request forever.

text
               |> Map.put(:stream, chunks)
               |> ReqLLM.StreamResponse.classify()
 
-            if classification.type == :tool_calls do
-              tool_calls =
+            tool_calls =
+              if classification.type == :tool_calls do
                 classification.tool_calls
                 |> normalize_tool_calls(chunk_tool_call_ids)
                 |> unprocessed_tool_calls(messages)
+              else
+                []
+              end
 
+            # An empty post-filter list means the model returned only invalid or
+            # already-processed tool calls, so `messages` would not advance.
+            # Recursing would re-send a byte-identical request forever (a
+            # no-progress loop, unbounded under `max_iterations: :infinity`), so
+            # treat it as terminal.
+            if tool_calls != [] do
               messages =
                 append_tool_call_turn(
                   messages,

Source: GitHub Commit 53325fd

Detection Methods for CVE-2026-82579

Indicators of Compromise

  • Repeated, byte-identical outbound requests from an ash_ai process to a configured LLM provider endpoint within a short window.
  • Elevated LLM provider billing or rate-limit responses tied to a single agent session.
  • Application logs showing continuous AshAi.ToolLoop iterations without new assistant or tool messages appended.
  • Model responses referencing tool_call_id values already present in prior turns of the same conversation.

Detection Strategies

  • Inspect running ash_ai deployments for the vulnerable version range 0.6.0 through < 1.0.0 in mix.lock or deps output.
  • Add per-session counters that track tool-call iterations and alert when a threshold is exceeded without state advancement.
  • Monitor LLM provider API call rates on a per-request-context basis and flag flatline conversations with growing call counts.

Monitoring Recommendations

  • Emit telemetry from AshAi.ToolLoop with iteration counts, unique message-list hashes, and tool-call identifiers.
  • Correlate spikes in LLM spend or 429 responses with specific agent sessions and untrusted data sources.
  • Log and review any tool_call_id reuse across turns as a strong signal of prompt injection targeting this class of flaw.

How to Mitigate CVE-2026-82579

Immediate Actions Required

  • Upgrade ash_ai to version 1.0.0 or later, which treats an empty post-filter tool-call list as terminal.
  • Audit agents currently configured with max_iterations: :infinity and cap them until the patched version is deployed.
  • Review recent LLM provider invoices and rate-limit events for signs of runaway loops.

Patch Information

The fix is committed in ash-project/ash_ai commit 53325fd and shipped in ash_ai1.0.0. Details are published in GitHub Security Advisory GHSA-rcx7-x2w5-mmc2, the Erlang Ecosystem Foundation CNA advisory, and OSV entry EEF-CVE-2026-82579.

Workarounds

  • Set a conservative finite value for max_iterations instead of :infinity to bound worst-case cost.
  • Reject or sanitize model output that references tool_call_id values already resolved in the current conversation.
  • Isolate agent workloads behind provider-side rate limits and budget alerts to contain unbounded request storms.
bash
# Update ash_ai to the patched release in mix.exs
# {:ash_ai, "~> 1.0"}
mix deps.update ash_ai
mix deps.get
mix compile

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

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.