Executive brief
Elixir's list inspection functions (inspect/1, List.to_string/1, List.to_charlist/1) can be triggered into uncontrolled recursion when processing specially crafted lists that exceed the printable character limit. An attacker who can control input to these functions can exhaust a BEAM node's memory and cause a denial of service, disrupting applications relying on Elixir.
Technical details
This is an uncontrolled recursion vulnerability in Elixir's list inspection logic. The root cause lies in Inspect.List's charlist classification branch in lib/inspect.ex: it checks only the first 4096 elements via List.ascii_printable?/2, then calls IO.chardata_to_string/1 on the entire list. If the list has a valid printable prefix beyond the limit but contains an invalid element (atom, out-of-range integer, or improper tail) later, the conversion raises ArgumentError. The exception handler interpolates inspect(list) into the error message, re-entering the same vulnerable code path. Because the nested inspect/1 is an argument to raise/1 (not in tail position), the stack is retained and grows monotonically; each recursion cycle re-walks the entire list, eventually causing the node to run out of memory or hit max_heap_size limits. List.to_charlist/1 has an identical rescue structure. The vulnerability is triggered only when the invalid element is beyond the 4096-character limit; within that limit, the error is caught and rendered safely.
Affected products
- Elixir Elixir 1.15.0-rc.0 before 1.18.5, 1.19.0-rc.0 before 1.19.6, 1.20.0-rc.0 before 1.20.4
Timeline
- 2026-08-28: disclosed