← Retour au blog
tech 28 May 2026

Atom Exhaustion: One Third of Our CVEs

Atom exhaustion accounts for a significant portion of denial-of-service vulnerabilities in the BEAM ecosystem. Learn how to avoid this common pitfall.

Article inspired by the original source
Atom Exhaustion Is Not a Footgun. It's One Third of Our CVEs ↗ erlef.org

Atom Exhaustion: An Underestimated Issue

In the vast world of cybersecurity, some vulnerabilities often fly under the radar until they become an evident threat. Atom exhaustion is a perfect example. In the BEAM ecosystem, which includes languages like Erlang and Elixir, this vulnerability manifests as uncontrolled resource consumption, leading to about 35.8% of the CVEs reported by the Erlang Ecosystem Foundation (EEF).

Understanding Atom Exhaustion

In BEAM, an atom is a literal constant stored in a global atom table that isn't garbage-collected. This table has a limited capacity. Once full, it causes the virtual machine to crash, making the system vulnerable to denial-of-service (DoS) attacks.

Dynamically creating atoms from non-finite values, especially user inputs, opens the door to these vulnerabilities. Functions like binary_to_atom/1 or list_to_atom/1 in Erlang, and String.to_atom/1 in Elixir can transform unpredictable user inputs into atoms, with potentially disastrous consequences.

Concrete Examples of Vulnerabilities

Consider a simple example in Elixir:

``elixir decoded_json = Jason.decode!(json_data, keys: :atoms) ``

Here, if json_data comes from an untrusted external source, each JSON key is converted into an atom, risking to fill the atom table if those keys are numerous and unpredictable.

Strategies to Avoid Exhaustion

The best practice is to avoid creating new atoms at runtime. Prefer using explicit lookup tables when the accepted values are known:

``erlang case Scheme of <<"http">> -> http; <<"https">> -> https; _ -> error end ``

When a lookup table isn't practical, use existing-atom variants that will raise an error instead of creating a new atom if it doesn't already exist:

``erlang binary_to_existing_atom(Value) ``

In Elixir, use String.to_existing_atom(value) to ensure safety.

Linting and Best Practices

For Elixir projects, the Credo linter offers a check for detecting unsafe calls to String.to_atom/1 and others. Enable the Credo.Check.Warning.UnsafeToAtom check to prevent vulnerabilities before they become CVEs.

Conclusion

Atom exhaustion is an easily avoidable vulnerability with the right practices and tools. Don't get caught by this often insidious but easily circumvented trap.

Let's discuss your project in 15 minutes.

atom exhaustion BEAM ecosystem denial of service Erlang Elixir
Deepthix newsletter · 100% AI · every Monday 8am

An AI agent reads tech for you.

Our AI agent scans ~200 sources per week and ships the best articles to your inbox Monday 8am. Free. One click to unsubscribe.

Visit the newsletter page →

Want to automate your operations?

Let's talk about your project in 15 minutes.

Book a call