CVE-2026-77856 Overview
CVE-2026-77856 is an uncontrolled resource allocation flaw [CWE-770] in the ash-project/ash_typescript library. The library, used with the Ash Framework in Elixir applications, converts client-supplied field names to atoms without validating that the field exists first. Because BEAM atoms are never garbage collected, an unauthenticated attacker can send requests with many distinct field names on a typed struct field and grow the atom table until the Erlang VM aborts. The issue affects ash_typescript versions from 0.11.0 up to but not including 0.18.0.
Critical Impact
An unauthenticated network attacker can crash the entire BEAM node by exhausting the atom table, taking down all Elixir applications running on the affected VM.
Affected Products
- ash-project/ash_typescript versions 0.11.0 through 0.17.x
- Elixir/Erlang applications using ash_typescript RPC with typed struct fields
- BEAM VM instances hosting vulnerable ash_typescript deployments
Discovery Timeline
- 2026-09-01 - CVE-2026-77856 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-77856
Vulnerability Analysis
The vulnerability resides in the resolve_typed_struct_field/2 function in lib/ash_typescript/rpc/field_processing/field_selector.ex. The function accepts a client-supplied field name and attempts to look it up in a typed struct's reverse map. When the lookup fails, the function falls back to String.to_atom/1 before any field-existence check runs. This behavior converts any arbitrary client input into a permanent atom.
BEAM atoms are stored in a global table with a default maximum of 1,048,576 entries. Atoms are never garbage collected. Once the atom table fills, the Erlang VM aborts with system_limit, terminating every application hosted on that node. An attacker exploits this by issuing requests that include large numbers of unique field names against endpoints processing typed struct fields.
Root Cause
The root cause is a sequencing error: atom creation runs before field validation. The String.to_atom/1 call trusts client input and permanently allocates atoms for names that would otherwise be rejected as unknown fields. This violates the well-established Erlang guidance to never call String.to_atom/1 on untrusted external input.
Attack Vector
Exploitation requires only network access to any endpoint exposing ash_typescript RPC with a typed struct field. No authentication, user interaction, or elevated privileges are needed. An attacker sends a series of RPC requests containing distinct random strings as typed struct field names. Each unresolvable name consumes a permanent atom slot until the VM aborts.
defp resolve_typed_struct_field(field_name, reverse_map) when is_binary(field_name) do
case Map.get(reverse_map, field_name) do
- nil ->
- formatter = AshTypescript.Rpc.input_field_formatter()
- converted = FieldFormatter.parse_input_field(field_name, formatter)
- if is_atom(converted), do: converted, else: String.to_atom(converted)
-
- internal ->
- internal
+ # Never mint an atom here: an unresolved name has no matching field atom, so
+ # it stays a string and fails validate_field_exists_in_fields!/4 as an unknown
+ # field. Minting would only let client input grow the atom table.
+ nil -> resolve_field_name(field_name)
+ internal -> internal
end
end
Source: GitHub Commit 0ab5c83a. The patch replaces the atom-minting fallback with resolve_field_name/1, which leaves unresolved names as strings so they fail downstream field validation.
Detection Methods for CVE-2026-77856
Indicators of Compromise
- Steady growth in the BEAM atom count observed via :erlang.system_info(:atom_count) without corresponding deployments or new features.
- Repeated RPC requests to ash_typescript endpoints containing high-entropy or randomized field names on typed struct fields.
- Unexpected VM aborts with system_limit errors referencing atom table exhaustion in crash dumps.
Detection Strategies
- Instrument application telemetry to sample atom_count and atom_limit from :erlang.system_info/1 and alert on sustained upward trends.
- Inspect HTTP access logs for RPC endpoints receiving large volumes of requests with varying field-name parameters from the same client.
- Add integration tests that assert unknown field names on typed struct fields return validation errors without increasing the atom count.
Monitoring Recommendations
- Emit :telemetry events tracking atom table utilization and forward them to a centralized monitoring backend.
- Enable request-level logging on ash_typescript RPC handlers to capture the full set of field names submitted per request.
- Set alerting thresholds when atom table usage exceeds 70% of the configured +t limit.
How to Mitigate CVE-2026-77856
Immediate Actions Required
- Upgrade ash_typescript to version 0.18.0 or later, which contains the fix in commit 0ab5c83a.
- Audit all custom code paths that call String.to_atom/1 or List.to_atom/1 on external input and replace them with safer alternatives.
- Restart affected BEAM nodes after upgrading to reset the atom table to a baseline state.
Patch Information
The fix is available in ash_typescript 0.18.0. The upstream patch is documented in the GitHub Security Advisory GHSA-rj47-h936-4cxw and applied in commit 0ab5c83a. Additional context is available at the CNA advisory and OSV entry EEF-CVE-2026-77856.
Workarounds
- Place a reverse proxy or web application firewall in front of ash_typescript RPC endpoints to reject requests containing unusually large or high-entropy field name sets.
- Apply per-client rate limiting to RPC endpoints to slow the rate at which an attacker can submit unique field names.
- Increase the BEAM atom limit temporarily via the +t VM flag as a stopgap, understanding this only delays exhaustion rather than preventing it.
# Update mix.exs to require the patched version
# {:ash_typescript, "~> 0.18.0"}
mix deps.update ash_typescript
mix deps.get
mix compile
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

