CVE-2026-48860 Overview
CVE-2026-48860 is an authorization bypass vulnerability [CWE-863] in the Erlang/OTP ssl application, specifically in the inet_tls_dist module that governs Erlang distribution over TLS. The flaw allows any holder of a CA-signed TLS certificate to bypass the LAN allowlist enforced by inet_tls_dist:check_ip/1 and obtain full Erlang distribution access to the target node. Successful exploitation grants attackers access to rpc:call/4 and code:load_binary/3, enabling arbitrary code execution on the Erlang node.
Critical Impact
Remote attackers presenting any CA-signed TLS certificate can join an Erlang cluster and execute arbitrary code through distribution protocol primitives, bypassing the intended LAN-only restriction.
Affected Products
- Erlang/OTP versions from OTP 26.0 before 29.0.2
- Erlang/OTP 28.5.0.x before 28.5.0.2
- Erlang/OTP 27.3.4.x before 27.3.4.13 (corresponding to ssl 11.0 before 11.7.2, 11.6.0.2, and 11.2.12.9)
Discovery Timeline
- 2026-06-10 - CVE-2026-48860 published to NVD
- 2026-06-10 - Last updated in NVD database
Technical Details for CVE-2026-48860
Vulnerability Analysis
The vulnerability resides in lib/ssl/src/inet_tls_dist.erl, the module responsible for enforcing the LAN allowlist on incoming Erlang distribution connections established over TLS. The check_ip/1 function is supposed to compare the remote peer's IP address against the configured subnet mask. Instead of fetching the remote peer address, the function calls inet:sockname/1, which returns the address of the local end of the socket. Both compared values therefore originate from the local node, so the subnet mask comparison always succeeds regardless of where the connection originates.
Any attacker on an adjacent network who can complete a TLS handshake with a certificate signed by a trusted CA passes the allowlist check. Once connected, the attacker speaks the Erlang distribution protocol and can invoke rpc:call/4 to execute remote procedure calls or code:load_binary/3 to load attacker-supplied bytecode into the runtime.
Root Cause
The root cause is the use of the wrong API to identify the peer. inet:sockname/1 returns the local socket address, while inet:peername/1 returns the remote address. The check confuses the two, producing a tautological comparison that defeats the security boundary.
Attack Vector
Exploitation requires network reach to the Erlang distribution TLS port and a TLS certificate signed by a CA trusted by the target node. No prior authentication to the Erlang cluster or knowledge of the cluster cookie is required to bypass the IP allowlist itself.
end,
{ok, Ifaddrs} ?= inet:getifaddrs(),
{ok, Netmask} ?= find_netmask(IP, Ifaddrs),
- {ok, {PeerIP, _}} ?= inet:sockname(Socket),
+ {ok, {PeerIP, _}} ?= inet:peername(Socket),
ok ?= if is_tuple(PeerIP) -> ok;
true -> {error, {no_ip_address, PeerIP}}
end,
Source: GitHub OTP Commit 0209a6df. The patch replaces inet:sockname(Socket) with inet:peername(Socket) so PeerIP reflects the remote address and the subnet allowlist check evaluates the actual peer.
Detection Methods for CVE-2026-48860
Indicators of Compromise
- Unexpected inbound TLS connections to the Erlang distribution port (commonly in the EPMD-assigned range) from hosts outside the documented LAN allowlist.
- Erlang nodes recording new distribution peers, RPC activity, or dynamic module loads via code:load_binary/3 that do not correlate with known cluster members.
- TLS handshake logs showing client certificates issued by unexpected CAs being accepted by Erlang nodes.
Detection Strategies
- Audit Erlang nodes for the presence of inet_tls_dist configuration and verify the installed OTP and ssl application versions against fixed releases.
- Correlate network flow telemetry with the Erlang node's expected peer list, alerting when distribution connections originate outside configured subnets.
- Monitor for runtime use of rpc:call/4, code:load_binary/3, and erlang:load_module/2 from nodes that should not be issuing such commands.
Monitoring Recommendations
- Enable SASL and ssl debug logging on production Erlang nodes to capture distribution connection establishment and the certificates presented.
- Forward distribution-related log events to a centralized SIEM and build alerts for new peer node names appearing in cluster membership.
- Track outbound and inbound traffic on the Erlang distribution TLS port at the network boundary and alert on connections that cross trust zones.
How to Mitigate CVE-2026-48860
Immediate Actions Required
- Upgrade to Erlang/OTP 29.0.2, 28.5.0.2, or 27.3.4.13 (or later) so that inet_tls_dist:check_ip/1 uses inet:peername/1.
- Restrict network access to the Erlang distribution TLS port using host firewalls or network ACLs that only permit known cluster members.
- Replace any broadly trusted CA bundle used for distribution TLS with a private CA dedicated to signing only legitimate cluster node certificates.
Patch Information
The fix is published in OTP 29.0.2, 28.5.0.2, and 27.3.4.13, corresponding to ssl versions 11.7.2, 11.6.0.2, and 11.2.12.9. Reference the GitHub Security Advisory GHSA-gp7x-mfv6-52cv, the CNA advisory, and the OSV record EEF-CVE-2026-48860. Erlang versioning semantics are documented in the Erlang Versioning Documentation.
Workarounds
- Configure mutual TLS for Erlang distribution using a dedicated private CA so that only nodes holding cluster-issued certificates can complete the TLS handshake.
- Bind the Erlang distribution listener to a management interface unreachable from untrusted networks, and enforce firewall rules limiting source addresses to known cluster peers.
- Disable Erlang distribution entirely on nodes that do not require clustering by starting the runtime without -name or -sname flags.
# Configuration example: restrict distribution listener and enforce mTLS with a private CA
iptables -A INPUT -p tcp --dport 4370:4399 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 4370:4399 -j DROP
# vm.args fragment - require client certificate from private cluster CA
-proto_dist inet_tls
-ssl_dist_optfile /etc/erlang/ssl_dist.conf
# /etc/erlang/ssl_dist.conf
[{server, [{cacertfile, "/etc/erlang/pki/cluster-ca.pem"},
{certfile, "/etc/erlang/pki/node-cert.pem"},
{keyfile, "/etc/erlang/pki/node-key.pem"},
{verify, verify_peer},
{fail_if_no_peer_cert, true}]},
{client, [{cacertfile, "/etc/erlang/pki/cluster-ca.pem"},
{certfile, "/etc/erlang/pki/node-cert.pem"},
{keyfile, "/etc/erlang/pki/node-key.pem"},
{verify, verify_peer}]}].
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

