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.