CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-21619
2.00.02%

Unsafe Deserialization in Erlang Hex Ecosystem (hex_core, rebar3)

Alon Barad
Alon Barad
Software Engineer

Mar 1, 2026·5 min read·9 visits

PoC Available

Executive Summary (TL;DR)

Vulnerable Erlang/Elixir build tools deserialize untrusted API responses using unsafe methods. An attacker controlling a package mirror or network position can inject malicious Erlang terms, causing VM crashes (DoS) or executing arbitrary code.

A critical unsafe deserialization vulnerability exists in `hex_core`, the reference implementation for the Hex package manager API, affecting downstream tools like `hex` and `rebar3`. The flaw stems from the use of the unsafe `binary_to_term/1` function when processing HTTP response bodies, allowing attackers to trigger Denial of Service via atom table exhaustion or potentially achieve Remote Code Execution through object injection.

Vulnerability Overview

The vulnerability resides in hex_core, a foundational library used by the Erlang and Elixir ecosystems to interact with the Hex package registry. Specifically, the library failed to validate serialized Erlang terms received from the Hex API before decoding them. This affects hex (the Mix package manager) and rebar3 (the Erlang build tool), meaning the vulnerability extends to the majority of build pipelines in this ecosystem.

When a client requests package information, the Hex API often returns data encoded in the Erlang External Term Format. The vulnerable code used the native binary_to_term/1 function to decode this data. This function is inherently unsafe when applied to untrusted input because it deserializes data into memory without restriction, creating atoms and other complex structures directly within the Erlang VM.

By spoofing a Hex API response—either through a compromised mirror, a Man-in-the-Middle (MitM) attack, or a malicious proxy—an attacker can supply a crafted binary payload. This payload is processed automatically by the build tool, leading to immediate resource exhaustion or the instantiation of malicious objects.

Root Cause Analysis

The root cause is the misuse of binary_to_term/1 for processing external data (CWE-502). In the Erlang Beam VM, atoms (literals used as identifiers) are stored in a non-garbage-collected global table with a fixed limit (default 1,048,576). Once created, an atom persists until the VM terminates. The binary_to_term/1 function creates new atoms if they do not already exist in the table.

Mechanism 1: Atom Table Exhaustion (DoS) An attacker can construct a payload containing hundreds of thousands of unique, random atoms. When the client deserializes this payload, the VM attempts to register all new atoms. This rapidly fills the atom table. Once the limit is reached, the Erlang VM allocates no further memory for atoms and crashes instantly, terminating the build process.

Mechanism 2: Object Injection (RCE) The Erlang External Term Format supports the serialization of anonymous functions (funs). If an attacker injects a serialized fun into the response, and the application logic subsequently invokes that term (or passes it to a function expecting a callback), the attacker's code executes within the context of the build tool. This allows for arbitrary system command execution via os:cmd/1 wrapped inside the injected function.

Code Analysis

The vulnerability existed in the HTTP response handling logic within src/hex_api.erl. The code implicitly trusted the Content-Type: application/vnd.hex+erlang header and passed the body directly to the deserializer.

Vulnerable Code (Pre-Patch):

%% src/hex_api.erl
case binary:match(ContentType, ?ERL_CONTENT_TYPE) of
    {_, _} ->
        %% CRITICAL: Unsafe deserialization of untrusted binary data
        %% This permits atom creation and function instantiation
        {ok, {Status, RespHeaders, binary_to_term(RespBody)}};
    nomatch ->
        {ok, {Status, RespHeaders, nil}}
end.

Patched Code (Post-Patch):

The fix introduces two layers of defense. First, it switches to binary_to_term/2 with the safe option, which forbids the creation of new atoms. Second, it implements a recursive validator that ensures the deserialized term only contains inert data types (lists, tuples, maps, numbers, binaries) and explicitly rejects dangerous types like fun or port.

%% src/hex_api.erl
case binary:match(ContentType, ?ERL_CONTENT_TYPE) of
    {_, _} ->
        %% FIX 1: Use the [safe] flag to prevent atom creation
        case binary_to_term(RespBody, [safe]) of
            Term ->
                %% FIX 2: Recursively validate the structure against a whitelist
                case hex_safe_binary_to_term:validate(Term) of
                    ok ->
                        {ok, {Status, RespHeaders, Term}};
                    {error, Reason} ->
                        {error, Reason}
                end;
            Error ->
                {error, Error}
        end;
    nomatch ->
        ...
end.

Exploitation Methodology

To exploit this vulnerability, an attacker requires a position in the network to modify traffic or control over a repository mirror configured by the victim. The attack does not require authentication to the victim's machine, but it does require the victim to initiate a build command (User Interaction).

  1. Interception: The attacker intercepts a request to the Hex API (e.g., during mix deps.get). If TLS validation is disabled or compromised, this is trivial. Alternatively, the attacker sets up a rogue mirror.
  2. Payload Generation: The attacker generates a malicious payload using Erlang:
    %% DoS Payload: List of 1M unique atoms
    Payload = term_to_binary([list_to_atom(integer_to_list(I)) || I <- lists:seq(1, 1000000)]).
     
    %% RCE Payload: Embedded fun
    Payload = term_to_binary(fun() -> os:cmd("rm -rf /") end).
  3. Delivery: The attacker serves this binary as the HTTP response body with the header Content-Type: application/vnd.hex+erlang.
  4. Execution: The victim's client receives the response, deserializes it, and either crashes immediately (DoS) or stores the malicious term. If the term is a fun and the client logic executes it (e.g., expecting a callback), the payload triggers.

Impact Assessment

Despite the CVSS v4.0 score of 2.0 (which heavily penalizes the Attack Requirements and User Interaction), the technical impact is critical for affected environments. Development and CI/CD pipelines are the primary targets.

  • Availability (High): The most reliable outcome is a Denial of Service. A crash in rebar3 or mix halts deployment pipelines, potentially blocking releases or causing operational downtime in automated environments.
  • Integrity & Confidentiality (High - Conditional): If the RCE vector is successfully triggered, the attacker gains the privileges of the user running the build tool. In CI/CD environments, this often equates to root access or access to sensitive secrets (API keys, signing certificates) stored in the build environment.
  • Supply Chain Risk: Compromising a developer's machine via a build tool allows an attacker to inject backdoors into the software being built, propagating the attack further downstream.

Official Patches

hexpmhex_core v0.12.1 fix commit

Fix Analysis (2)

Technical Appendix

CVSS Score
2.0/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
EPSS Probability
0.02%
Top 97% most exploited

Affected Systems

rebar3 < 3.27.0hex < 2.3.2hex_core < 0.12.1

Affected Versions Detail

Product
Affected Versions
Fixed Version
hex_core
hexpm
< 0.12.10.12.1
hex
hexpm
< 2.3.22.3.2
rebar3
erlang
< 3.27.03.27.0
AttributeDetail
CWE IDCWE-502 (Deserialization of Untrusted Data)
Secondary CWECWE-400 (Uncontrolled Resource Consumption)
Attack VectorNetwork
CVSS v4.02.0 (Low)
ImpactDoS / RCE
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1195Supply Chain Compromise
Initial Access
T1499Endpoint Denial of Service
Impact
T1059Command and Scripting Interpreter
Execution
CWE-502
Deserialization of Untrusted Data

The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.

Known Exploits & Detection

GitHub AdvisoryVendor advisory describing atom exhaustion and object injection vectors.

Vulnerability Timeline

Fix committed to hex_core and hex
2026-02-27
rebar3 v3.27.0 released with fix
2026-02-27
CVE-2026-21619 Published
2026-02-27

References & Sources

  • [1]GHSA-hx9w-f2w9-9g96: Unsafe Deserialization in hex_core
  • [2]Erlang Documentation: binary_to_term/1

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.