CVE-2026-78228 in ash_oban
Summary
by MITRE • 08/30/2026
Uncontrolled Recursion vulnerability in ash-project ash_oban allows a user who can drive a trigger's on_error action to fail on the final attempt to exhaust worker CPU and memory, denying service.
The generated worker's atomic handle_error/4 runs the trigger's on_error action on a job's final attempt inside a rescue that, when the action itself raises, calls handle_error/4 again with the same job. The job's attempt still equals max_attempts, so it re-enters the same clause and re-runs the failing action, with no exit. Any deterministic on_error failure (a data-layer outage, a misconfigured action, or a record the action rejects) loops forever; because the recursive call is not in tail position, each iteration retains a formatted stacktrace and the process heap grows without bound while the failing statement is re-issued against the data layer until the runtime kills the worker.
This issue affects ash_oban: from 0.8.0-rc.1 before 0.8.14.
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 08/30/2026
The vulnerability identified in ash_oban represents a critical uncontrolled recursion flaw that leads to resource exhaustion and subsequent denial of service within the application environment. This issue specifically impacts versions ranging from 0.8.0-rc.1 up to, but not including, version 0.8.14. The core of the problem lies in the implementation of the atomic handle_error/4 function, which is responsible for managing job failures and executing designated error handling actions. When a trigger's on_error action fails during its final attempt, the system enters an infinite recursive loop rather than properly terminating or escalating the failure state to a manageable level. This behavior allows any user with the ability to influence or drive the trigger's on_error action to exploit this flaw by ensuring that the action consistently raises an exception upon execution.
From a technical perspective, the vulnerability stems from the structural design of the error handling logic within the worker process. The handle_error/4 function is invoked when a job fails and attempts to execute the configured on_error action. If this action itself throws an exception or raises an error, the code catches it using a rescue block and subsequently calls handle_error/4 again with the same job record. Crucially, because the job's attempt count remains equal to its maximum allowed attempts during this recursive call, the function re-enters the exact same conditional clause that triggered the initial failure. This creates an infinite loop where the failing statement is repeatedly issued against the data layer or external service without any mechanism for exit. The recursion is not implemented in tail position, which means that each iteration of the loop retains a formatted stack trace on the process heap. As this cycle continues indefinitely, the memory footprint of the worker process grows without bound due to the accumulation of these stack traces and associated state data.
The operational impact of this vulnerability is severe, primarily manifesting as a denial of service condition for both the specific worker process and potentially the broader system depending on resource constraints. The unbounded growth of the process heap consumes available memory until the Erlang runtime environment forcibly kills the worker to prevent total node collapse. This results in the loss of any state held by that worker, including pending jobs or transactional integrity if not properly isolated. Furthermore, the repeated re-issuance of the failing statement against the data layer can cause additional strain on database connections and network resources, potentially degrading performance for other services sharing those infrastructure components. An attacker who can control the input to the on_error action, such as by submitting a job with specific malformed or rejected data, can reliably trigger this condition, effectively taking down critical background processing capabilities.
This vulnerability aligns closely with CWE-674, which describes Uncontrolled Recursion, where software does not properly limit the depth of recursive calls leading to resource exhaustion. Additionally, from an offensive security perspective, this flaw facilitates Denial of Service attacks as categorized under MITRE ATT&CK technique T1499, specifically Endpoint Denial of Service via resource consumption. The exploitation vector relies on the attacker's ability to drive a trigger's error handling path into failure, highlighting the importance of robust input validation and state management in background job processing systems.
To mitigate this vulnerability, organizations must upgrade ash_oban to version 0.8.14 or later, where the recursive logic has been corrected to prevent infinite loops during final attempt failures. In environments where immediate upgrading is not feasible, temporary mitigations should focus on isolating worker processes with strict memory limits and monitoring for abnormal heap growth patterns that indicate recursion issues. Implementing circuit breakers around external data layer calls within error handling actions can also help prevent the repeated re-issuance of failing statements, thereby reducing the impact even if the recursive loop is partially triggered. Ensuring that on_error actions are idempotent and handle their own exceptions gracefully without raising unhandled errors is a critical defensive coding practice to avoid entering this vulnerable state in future implementations.