Atom Exhaustion Is Not a Footgun. It's One Third of Our CVEs

birdculture1 pts0 comments

Erlang Ecosystem Foundation - Supporting the BEAM community

Atom Exhaustion: A Known Issue That Keeps Becoming a CVE

May 26, 2026 by Jonatan Männchen

Posted in Security

Tags

security

atom-exhaustion

vulnerability

dos

Correction (2026-05-29): An earlier version of this post stated that<br>approximately one third of EEF CNA CVEs are caused by atom exhaustion. The<br>correct figure is approximately one tenth. The text below has been updated.

Around one third of CVEs published by the Erlang Ecosystem Foundation CNA fall<br>into the category of uncontrolled resource consumption (CWE-400). In the BEAM<br>ecosystem, roughly one third of those are caused by one recurring issue: atom<br>exhaustion, making it approximately one tenth of all CVEs . You can find the<br>current distribution on the EEF CNA’s Common Weaknesses<br>page.

Atom exhaustion is a denial-of-service vulnerability. Atoms are not garbage<br>collected and are stored in a global atom table, and once it fills up, the VM<br>crashes. Creating atoms from non-finite values, especially user-supplied input,<br>is therefore a latent DoS waiting to happen.

This is not limited to obvious calls such as binary_to_atom/1,<br>list_to_atom/1, String.to_atom/1, or List.to_atom/1. Some dangerous<br>patterns are less obvious:

% Erlang: dynamic atom creation through interpolation<br>list_to_atom("field_" ++ UserInput)<br># Elixir: decoding JSON with atom keys<br>Jason.decode(json, keys: :atoms)<br># Elixir: dynamic atom creation through interpolation<br>:"field_#{user_input}"

What makes this class of vulnerability persistent is not carelessness. It often<br>appears in code where the input was assumed to be controlled or finite. URI<br>schemes are a good example: it may feel like there are only a few schemes to<br>handle, but if the value comes from external input, the set is no longer<br>guaranteed to be finite.

Creating atoms from input is unsafe unless the set of possible values is<br>finite, known, and enforced.

The safest approach is to avoid creating new atoms at runtime entirely. Prefer<br>explicit lookup tables when the accepted values are known:

% Erlang<br>case Scheme of<br>> -> http;<br>> -> https;<br>_ -> error<br>end

When a lookup table is not practical, use the safer existing-atom variants,<br>which will raise an error instead of creating a new atom:

% Erlang<br>binary_to_existing_atom(Value)<br>list_to_existing_atom(Value)<br># Elixir<br>String.to_existing_atom(value)<br>List.to_existing_atom(value)

Linters can help catch these patterns before they become vulnerabilities. For<br>Elixir projects, consider enabling Credo’s<br>Credo.Check.Warning.UnsafeToAtom, which flags unsafe<br>calls to String.to_atom/1, List.to_atom/1, Module.concat/1,2, and<br>Jason.decode/2 with keys: :atoms. The check is disabled by default.

If you maintain an Erlang or Elixir project, search your codebase for atom<br>creation from binaries, strings, JSON keys, URI components, headers, and<br>configuration values. This is one of the easiest vulnerability classes to fix<br>before it becomes a CVE.

For more detailed guidance, see the EEF Security Working Group’s<br>guide on preventing atom exhaustion.

Recent posts

Atom Exhaustion: A Known Issue That Keeps Becoming a CVE

May 26, 2026 by Jonatan Männchen

The EEF board 2026 Election Vote is Over

May 19, 2026 by EEF

Announcing the EEF 2026 board election candidates

May 8, 2026 by ErlEF

nx

announcements

agm

bio

cve

cna

otp

dos

qnx

epmd

axon

icfp

port

worm

board

aegis

virus

grisp

erlang

papers

funding

scidata

security

rabbitmq

livebook

explorer

embedded

programs

elections

developer

marketing

education

awareness

fellowship

newsletter

guidelines

sponsorship

supply-chain

cybersecurity

vulnerability

atom-exhaustion

machine learning

meet-the-sponsors

getting-to-know-us

vulnerability-disclosure

atom exhaustion erlang vulnerability atoms elixir

Related Articles