Severity by source
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Cursor arrives via HTTP query parameter on network-accessible endpoints; no credentials required on public APIs; pure availability impact with no confidentiality or integrity effect.
Primary rating from Vendor (EEF).
CVSS VectorVendor: EEF
Lifecycle Timeline
2DescriptionCVE.org
Uncontrolled Resource Consumption vulnerability in ash-project ash allows an attacker to exhaust the memory of the node via a crafted keyset pagination cursor.
Read actions with keyset pagination deserialize the client-supplied page[:after] or page[:before] cursor in decode_values/2 in lib/ash/page/keyset.ex, which base64-decodes the value and passes it to :erlang.binary_to_term/2 without bounding its size. The Erlang external term format supports zlib-compressed payloads, which the decoder inflates transparently, so a cursor of a few kilobytes can allocate tens of megabytes of heap in a single call. Ash itself only ever encodes cursors uncompressed, so the decoder accepts a term shape its encoder never produces. Concurrent requests aggregate these allocations and can terminate the node.
This issue affects ash: from 1.17.0 before 3.31.1.
AnalysisAI
Memory exhaustion via decompression bomb in Ash Framework's keyset pagination can terminate Erlang nodes running versions 1.17.0 through 3.31.0. The decode_values/2 function in lib/ash/page/keyset.ex deserializes client-supplied page[:after] or page[:before] cursors using :erlang.binary_to_term/2 without rejecting compressed Erlang external term format payloads or bounding the deserialized size, allowing a cursor of a few kilobytes on the wire to inflate to tens of megabytes of heap per request. No active exploitation (CISA KEV) has been identified, but the attack is mechanically trivial for any caller reaching a keyset-paginated endpoint, and the vendor patch test suite includes a working reproduction payload.
Technical ContextAI
Ash is a declarative resource framework for Elixir/Phoenix applications (CPE: cpe:2.3:a:ash-project:ash:*:*:*:*:*:*:*:*). Keyset pagination encodes cursors as base64 of :erlang.term_to_binary/1 output - the Erlang external term format (ETF). The vulnerable decode_values/2 path calls Base.decode64!/1 followed by non_executable_binary_to_term([:safe]), which maps to :erlang.binary_to_term(binary, [:safe]). The :safe flag prevents atom and function creation (guarding code execution) but does not prevent memory allocation from compressed ETF payloads. ETF tag 0x50 (decimal 80) signals a zlib-compressed payload that the BEAM runtime inflates transparently before materializing the term - a 2-million-element integer list compressed at level 9 arrives as roughly 8 KB on the wire and allocates tens of megabytes during deserialization. The root cause is CWE-502 (Deserialization of Untrusted Data): Ash's own encoder never produces compressed ETF, yet the decoder accepted a term shape its encoder never emits.
RemediationAI
Upgrade ash to version 3.31.1 or later; the fix is in commit 1816b103af975221210478d61db20adcea700319 (https://github.com/ash-project/ash/commit/1816b103af975221210478d61db20adcea700319) and the advisory is at https://github.com/ash-project/ash/security/advisories/GHSA-j35q-v8h8-7mwq. The patch adds two guards in check_keyset_size/2: compressed ETF payloads (tag byte 0x50) are unconditionally rejected before any inflation occurs, and uncompressed cursors are capped at 10 KiB by default (configurable via config :ash, max_keyset_byte_size: <bytes> in config/config.exs for deployments with unusually large sort values). If immediate upgrade is not possible, add a WAF or reverse-proxy rule to reject requests where page[after] or page[before] exceeds a few hundred bytes - legitimate cursors encoding a single record's sort values are always well below this threshold, so there is no functional impact on valid clients. Secondarily, rate-limit paginated endpoints per-IP or per-authenticated-user to slow aggregated allocation attacks; this reduces but does not eliminate risk.
An issue was discovered in the ash crate before 0.33.1 for Rust. Rated critical severity (CVSS 9.8), this vulnerability
Atom table exhaustion in the Ash framework (Elixir) allows an unauthenticated remote attacker to crash a BEAM node by su
An authorization bypass in the Ash framework (Elixir) lets authenticated, lower-privileged actors recover values they ar
Information disclosure in the Ash framework for Elixir (versions 2.6.0 up to but not including 3.34.6) lets an authentic
Private argument injection in the Ash Elixir framework (versions 3.0.0 through 3.29.2) allows end users to set action ar
Persistent record-level denial of service in the ash Elixir resource framework (versions 3.6.3-3.32.1) lets any actor wh
Integer overflow in Ash Framework's vector encoding corrupts stored vectors in any Elixir application using Ash versions
CPU exhaustion in Ash Framework's string type constraint handler allows denial of service against Elixir applications th
Unbounded string storage in Ash Framework versions 0.10.0 through 3.32.x allows unauthenticated attackers to bypass max_
Memory exhaustion in Ash Framework's runtime filter engine allows an attacker controlling filter inputs to crash an Elix
Silent record overwrite in Ash's ETS and Mnesia data layers allows any actor who can supply a primary key on a create ac
Record-level authorization bypass in Ash (ash-project) versions 3.4.44 through 3.32.1 silently leaks denied records to a
Same weakness CWE-502 – Deserialization of Untrusted Data
View allSame technique Deserialization
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-54937