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

CVE-2026-77956: Ash AI Code Injection RCE Vulnerability

CVE-2026-77956 is a code injection flaw in ash_ai that enables unauthenticated attackers to execute arbitrary Elixir code remotely. This article covers the technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-77956 Overview

CVE-2026-77956 is a code injection vulnerability [CWE-94] in the ash_ai library from the ash-project ecosystem. The flaw resides in AshAi.Actions.Prompt, which evaluates prompt content through EEx.eval_string/2. When a prompt action uses the fn input, context -> ... end form documented in the library, attacker-controlled request data flows into the prompt text. That text is then compiled and executed as an EEx template, which is Elixir source code. A payload such as <%= System.cmd(...) %> runs on the server before any language model request is made. The issue affects ash_ai versions 0.1.0 through versions prior to 1.0.0.

Critical Impact

Remote, unauthenticated attackers who can reach a prompt action can execute arbitrary Elixir code on the host, resulting in full server compromise.

Affected Products

  • ash-project ash_ai starting at version 0.1.0
  • ash-project ash_ai versions prior to 1.0.0
  • Elixir applications embedding AshAi.Actions.Prompt with function-supplied prompt content

Discovery Timeline

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

Technical Details for CVE-2026-77956

Vulnerability Analysis

The ash_ai library provides a prompt-driven action abstraction that lets developers define generative AI prompts as either static templates or as a two-argument function of the form fn input, context -> ... end. The build_context/3 function in lib/ash_ai/actions/prompt.ex retrieves the configured prompt and, when the prompt is a function, invokes it with request-derived input and context. The returned string is then passed through EEx.eval_string/2.

Because action arguments frequently include untrusted request data, an attacker who can invoke a prompt action can inject EEx tags into the resulting string. EEx compiles those tags into Elixir source and executes them within the application process. The prior code path was annotated with # sobelow_skip ["RCE.EEx"], which suppressed the Sobelow static analysis warning that would normally flag this pattern.

Root Cause

The root cause is unsafe evaluation of dynamically constructed template strings. Content produced at runtime from user input was treated as a trusted EEx template rather than opaque text, conflating data with code.

Attack Vector

An unauthenticated remote client submits input to any Ash action configured with a function-form prompt. The user-supplied value is interpolated into the prompt string returned by the function. When EEx.eval_string/2 compiles that string, embedded expressions like <%= System.cmd("id", []) %> execute as native Elixir. Exploitation requires only reachability to the prompt action.

text
     defp unwrap_result(%{result: value}), do: value
     defp unwrap_result(value), do: value
 
-    # sobelow_skip ["RCE.EEx"]
     defp build_context(input, opts, context) do
       prompt = Keyword.get(opts, :prompt, @prompt_template)
 
-      prompt_value =
-        case prompt do
-          func when is_function(func, 2) ->
-            func.(input, context)
-
-          other ->
-            other
-        end
-
-      normalize_to_context(prompt_value, input, context)
+      case prompt do
+        func when is_function(func, 2) ->
+          # Content returned from the prompt function is produced at runtime and
+          # is frequently built from action arguments (user input). Running it
+          # through EEx would compile that text as Elixir source (RCE), so it is
+          # used verbatim. EEx templating remains available for the statically
+          # configured prompt forms in the other clause.
+          normalize_to_context(func.(input, context), input, context, false)
+
+        other ->
+          normalize_to_context(other, input, context, true)
+      end
     end

Source: GitHub Commit e9948254b565. This patch stops treating function-supplied prompt content as an EEx template and only evaluates statically configured templates.

Stop Remote Code Execution Before It Runs

Singularity™ Endpoint detects and blocks exploit attempts at machine speed, including zero-days and novel attack techniques.

Stop Exploit Attempts

Detection Methods for CVE-2026-77956

Indicators of Compromise

  • Unexpected child processes spawned by the BEAM/Erlang VM runtime, such as shells, sh, bash, or System.cmd targets like id, curl, or wget.
  • Outbound network connections from the Elixir application host to unknown destinations shortly after HTTP requests to endpoints backed by prompt actions.
  • Request payloads containing EEx delimiters such as <%=, <%, or %> submitted to Ash action arguments.
  • New or modified files under the application working directory following requests to prompt-backed actions.

Detection Strategies

  • Inspect HTTP request logs for Ash action arguments containing EEx template syntax and Elixir module references such as System, File, :os, or Code.eval_string.
  • Correlate web-tier request logs with process-execution telemetry from the application host to identify command executions that follow prompt requests.
  • Audit source code for calls to EEx.eval_string/2 where the input is not a compile-time constant, and review any sobelow_skip ["RCE.EEx"] annotations.

Monitoring Recommendations

  • Enable process-creation and outbound network telemetry on hosts running ash_ai and alert on non-baseline child processes of the BEAM runtime.
  • Log the resolved prompt strings at debug level in staging environments to identify unsafe function-form prompts before production release.
  • Track deployed ash_ai versions across the fleet and alert on any host running a release below 1.0.0.

How to Mitigate CVE-2026-77956

Immediate Actions Required

  • Upgrade ash_ai to version 1.0.0 or later, which no longer evaluates function-supplied prompt content as EEx.
  • Inventory all Ash resources and actions using AshAi.Actions.Prompt with the fn input, context -> ... end prompt form and treat them as compromised until the upgrade is verified.
  • Rotate any secrets, API keys, or tokens accessible to the Elixir application process, since arbitrary code execution may have exposed them.
  • Restrict network access to endpoints backed by prompt actions until the patched version is deployed.

Patch Information

The fix is delivered in commit e9948254b565 and documented in GitHub Security Advisory GHSA-2g59-hg7m-qc83. The patched code passes function-produced prompt strings verbatim to normalize_to_context/4 with the EEx evaluation flag set to false. Only statically configured prompt templates continue to run through EEx. See the CNA advisory and OSV record for additional metadata.

Workarounds

  • Replace function-form prompts with statically configured templates that reference request data through explicit <%= @assign %> interpolation of pre-validated values.
  • If a function-form prompt is required before upgrading, strictly sanitize action arguments to remove <%, %>, and <%= sequences prior to string construction.
  • Deploy a reverse-proxy or web application firewall rule that rejects requests containing EEx delimiters in bodies targeting known prompt-action routes.
bash
# Configuration example: pin ash_ai to the patched version in mix.exs
# {:ash_ai, "~> 1.0.0"}
mix deps.update ash_ai
mix deps.get
mix compile --force

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.