CVE-2026-58227
Executive Summary
CVE-2026-58227 is a remotely exploitable denial-of-service vulnerability in the Erlang/OTP SSL application affecting all TLS/DTLS servers and clients running OTP versions from 23.2 through 27.3.4.14, 28.5.0.0 through 28.5.0.3, and 29.0.0 through 29.0.3. The flaw permits an unauthenticated remote attacker to trigger unbounded recursion by supplying two mutually cross-signed certificates in unordered form during a TLS/DTLS handshake, exhausting available memory and crashing the BEAM node. No authentication, completed handshake, or specialized access is required — only a TCP connection capable of transmitting a crafted Certificate message, making any Erlang-based service (web servers, message brokers, database proxies, IoT backends) vulnerable to trivial remote take-down.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability resides in the Erlang/OTP SSL application's certificate chain reconstruction logic, specifically within the ssl_certificate module. During a TLS or DTLS handshake, when a peer supplies an incomplete certificate chain that does not include all intermediate certificates, the server (or client) must reconstruct the chain by walking issuer relationships against its trusted store.
The relevant call path begins with ssl_certificate:handle_incomplete_chain/5, which receives the peer-provided certificate chain and forwards it to ssl_certificate:build_certificate_chain/5. That function, in turn, calls ssl_certificate:do_certificate_chain/7, which performs the issuer-relationship walk recursively. The chain accumulation logic has two critical deficiencies:
No cycle detection: The recursive walk does not maintain a set of already-visited certificates. Each certificate's issuer is looked up, and if found, that issuer is processed recursively — but if the issuer's own issuer points back to the original certificate, the function enters an infinite loop.
No depth limit: There is no maximum recursion depth parameter. Unlike typical certificate validation implementations that cap chain length (e.g., at 10 or 20 certificates), this code permits arbitrarily deep recursion.
The attack primitive is straightforward. An attacker crafts a Certificate handshake message containing exactly two certificates: Certificate A whose issuer is Certificate B, and Certificate B whose issuer is Certificate A. These are mutually cross-signed certificates. When the peer's incomplete chain reconstruction begins, it processes Certificate A, looks up its issuer (Certificate B), processes Certificate B, looks up its issuer (Certificate A), and returns to Certificate A — starting the cycle anew.
Each recursive call pushes a new stack frame onto the BEAM process's call stack and appends a certificate to the chain accumulator in the heap. Because there is no termination condition, the recursion continues indefinitely until either:
- The BEAM process exhausts its process-limited memory and crashes, OR
- The Erlang VM hits the system-wide memory ceiling (depending on
ERL_MAX_ETS_TABLESor OS-level RLIMIT) and terminates the entire node.
The crash affects the entire BEAM node, not just the attacking connection. Since a single Erlang VM typically hosts many services (OTP applications, supervisors, gen_servers), one malicious connection takes down all co-located services instantaneously. Both ssl:listen/2-based servers and ssl:connect/3-based clients are affected, meaning the flaw can be triggered against outbound TLS connections as well — a malicious TLS server could crash a connecting Erlang client.
The attack requires no special privileges, no authentication, and the certificates need not be trusted or valid in any way. The handshake can be aborted immediately after sending the Certificate message; the target does not need to complete the handshake for the vulnerability to trigger.
Exploitation Scenarios
The following attack chain outlines a realistic exploitation scenario against a production Erlang/OTP TLS server:
Scenario: Remote take-down of a RabbitMQ management TLS endpoint
Step 1 — Reconnaissance / Target Identification
The attacker scans for Erlang-based services by fingerprinting TLS responses. Erlang's SSL implementation emits distinctive characteristics in the ServerHello, including specific cipher suite preferences and a TLS extension order that differs from OpenSSL and GnuTLS. Shodan queries such as ssl:"Erlang" port:443 or port:5671 (RabbitMQ TLS) identify candidate targets. Alternatively, services like CouchDB (port 6984), MongooseIM (port 5222), and Telecommunication IMS nodes commonly expose Erlang TLS endpoints.
Step 2 — Weaponization / Trigger
The attacker generates two X.509 certificates with OpenSSL:
# Generate self-signed CA certificate A
openssl req -x509 -newkey rsa:2048 -keyout keyA.pem -out certA.pem -days 365 -nodes -subj "/CN=AttackerA"
# Create a signing request for certificate B, signed by A
openssl req -newkey rsa:2048 -keyout keyB.pem -out csrB.pem -nodes -subj "/CN=AttackerB"
openssl x509 -req -in csrB.pem -CA certA.pem -CAkey keyA.pem -CAcreateserial -out certB.pem -days 365
# Create a signing request for certificate A signed by B — the cross-sign
openssl req -newkey rsa:2048 -keyout keyA2.pem -out csrA.pem -nodes -subj "/CN=AttackerA"
openssl x509 -req -in csrA.pem -CA certB.pem -CAkey keyB.pem -CAcreateserial -out certA2.pem -days 365
The attacker now holds certA2.pem (issued by B) and certB.pem (issued by A) — a mutually cross-signed pair.
Step 3 — Payload / Execution
The attacker opens a TCP connection to the target port (e.g., 443) and initiates a TLS handshake. Using a modified TLS client (a small Python script with the ssl library and custom CERT_NONE verification disabled chain sending, or a raw TLS framing tool), the attacker sends:
ClientHellowith a supported cipher suite (e.g., TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)- Waits for
ServerHelloandCertificateRequest(if the server demands client auth) — OR immediately proceeds if the server sends itsCertificateandServerHelloDone - Sends the
Certificatehandshake message containing exactly the two crafted certificates in unordered form: firstcertA2.pem, thencertB.pem - Immediately closes the TCP connection (or simply stops sending further handshake records)
Step 4 — Post-Exploitation Impact
The target BEAM node enters the infinite recursion inside do_certificate_chain/7. Within milliseconds, the process stack grows hundreds of thousands of frames. The BEAM process exceeds its memory allocation, the emulator crashes, or the supervisor tree shuts down. The entire node — including unrelated services, databases, and message queues — becomes unavailable. Since Erlang nodes often form distributed clusters (via net_adm or erlang:connect_node), the crash may also destabilize connected nodes, propagating the outage across infrastructure. A single low-bandwidth packet (< 1 KB) achieves denial of service.
For DTLS targets (e.g., SIP/VoIP platforms, IoT gateways using DTLS), the same attack works over UDP, requiring only a spoofed source IP and a single crafted Certificate message.
Impact Assessment
Business Impact: This vulnerability enables unauthenticated remote denial of service against any Erlang/OTP-based TLS/DTLS endpoint. Affected services include RabbitMQ (AMQP over TLS), CouchDB, MongooseIM, EMQX, MQTT brokers, Riak, and custom OTP applications. The crash of a BEAM node produces complete service unavailability and may require manual intervention to restart, depending on the supervision strategy (a permanent child in a one_for_all supervision tree will restart, but a crash loop may occur if the attack is repeated).
Affected Systems: All OTP releases from 23.2 through 27.3.4.14, 28.5.0.0–28.5.0.3, and 29.0.0–29.0.3. This covers the vast majority of production Erlang deployments as of the advisory date. Both client-side and server-side TLS/DTLS usage is vulnerable.
Blast Radius: The attack surface is the TLS/DTLS handshake — no deep protocol state is required. Any service with an exposed TLS port using Erlang's ssl application is reachable. The effective CVSS vector is AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — CVSS base score 7.5 (High) — driven by network exploitability, no privileges, and complete availability loss. The EPSS score of 0.00350 (27.7th percentile) indicates low current exploitation likelihood but does not diminish the severity given the trivial attack complexity.
Data Integrity/Confidentiality: Not affected — the vulnerability is exclusively a denial-of-service condition. However, prolonged downtime in critical infrastructure (financial trading systems, healthcare messaging, telecommunication IMS cores) constitutes a severe operational impact.
Detection Guidance
Sigma Rule
title: Erlang OTP TLS Certificate Chain Recursion DoS Attempt
id: 4ec8b90c-6d72-4a54-9e05-9bc3f6e3b2f1
status: experimental
description: Detects TLS handshake messages containing unusually short certificate chains that are immediately followed by connection teardown, indicating a potential CVE-2026-58227 exploitation attempt.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-58227
tags:
- attack.t1190
- cve.2026-58227
logsource:
category: network_connection
product: linux
detection:
selection:
EventID: 5156 # Windows Filtering Platform connection event
Protocol: tcp
InitiatingProcessName|endswith:
- erl.exe
- beam.smp
filter:
ApplicationName|endswith:
- erl.exe
- beam.smp
condition: selection and not filter
level: high
falsepositives:
- Legitimate Erlang services frequently establish TLS connections
- High-volume messaging platforms may trigger false positives
fields:
- DestinationAddress
- DestinationPort
- InitiatingProcessName
YARA Rule
rule CVE_2026_58227_Erlang_SSL_Chain_DoS {
meta:
author = "Valter SiT Threat Intel"
description = "Detects TLS Certificate message payloads containing two mutually cross-signed certificates in a single handshake record, characteristic of CVE-2026-58227 exploitation."
cve = "CVE-2026-58227"
date = "2026-04-01"
severity = "high"
strings:
$x509_rdn_match = /CN=[A-Za-z0-9\-_]{1,64}/
$tls_cert_hdr = { 0b 00 00 00 02 } # Certificate message: entry count = 2
condition:
uint16(0) == 0x1603 and # TLS record, handshake type
$tls_cert_hdr at 4 and
# 2 or more certs in the message
# Look for the pattern where two certs share issuer/subject fields
# Simplified: check for exactly 2 cert lengths roughly equal
uint32(9) < 1024 and uint32(9) > 256 and # First cert length plausible
uint32(13) < 1024 and uint32(13) > 256 and # Second cert length plausible
# Cert count field present
uint8(8) == 2
}
Suricata IDS Rule
alert tls any any -> any any (msg:"CVE-2026-58227 Erlang TLS Certificate Chain Recursion DoS"; flow:to_server,established; tls.certificates; content:"|0b 00 00 00 02|"; depth:8; content:"|00|"; within:4; byte_test:2,>,1,4,relative; byte_test:2,>,1,0,relative; metadata:cve CVE-2026-58227; classtype:attempted-dos; sid:202658227; rev:1;)
Elastic Detection
EQL Query:
sequence by host.id, destination.ip with maxspan=30m
[ network where network.protocol == "tls" and event.action == "connection_attempted" and
destination.port in (443, 8443, 5671, 6984, 5222, 8883) and
not process.name in ("openssl", "curl", "wget") ]
[ network where network.protocol == "tls" and event.action == "connection_closed" and
source.bytes < 500 and destination.bytes < 2000 ]
[ process where event.action in ("terminated", "crash") and process.name : "beam.smp" ]
Splunk SPL Query
index=network sourcetype="tcp" earliest=-24h
| search dest_port IN (443, 8443, 5671, 6984, 5222, 8883)
| stats count by src_ip, dest_ip, dest_port, _time
| where count > 1
| join src_ip type=outer [
index=endpoint sourcetype="syslog" process_name="beam.smp"
| stats earliest(_time) as first_crash, latest(_time) as last_crash by host
| where first_crash > relative_time(now(), "-24h")
]
| table _time, src_ip, dest_ip, dest_port, count, first_crash, last_crash
| sort - count
Wazuh OSSEC Rule
<group name="erlang_tls_dos,">
<rule id="995406" level="12">
<decoded_as>syslog</decoded_as>
<field name="program_name">beam.smp</field>
<match>crash_dump|Stacktrace|Slogan: Killed|beam.smp crashed</match>
<description>Erlang BEAM node crash — possible CVE-2026-58227 TLS chain recursion exploitation</description>
<group>cve.2026-58227,</group>
<mitre>
<id>T1190</id>
</mitre>
</rule>
<rule id="995407" level="8">
<decoded_as>syslog</decoded_as>
<field name="program_name">beam.smp</field>
<match>Certificate chain too long|maximum chain length|chain_depth</match>
<description>Erlang SSL reported excessive certificate chain length — possible pre-crash indicator</description>
<group>cve.2026-58227,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch Confidence: 2/4 — CLAIMED (single source, not independently confirmed)
1. Immediate Mitigations (no vendor workaround exists):
- Upgrade OTP: The only confirmed remediation is upgrading to OTP 27.3.4.15, 28.5.0.4, or 29.0.4 (corresponding to ssl 11.2.12.11, 11.6.0.4, 11.7.4). Apply immediately.
- Network-level filtering: Place a reverse proxy (HAProxy, Nginx, Envoy) in front of Erlang TLS endpoints to terminate TLS and proxy plaintext or re-encrypt. This prevents direct raw TLS handshake records from reaching the vulnerable code.
- IP rate limiting: Limit TLS handshake rates per source IP at the network edge to slow down repeated exploitation attempts.
- Connection timeouts: Enforce aggressive handshake timeouts (e.g., 5–10 seconds) at the load balancer to truncate incomplete handshakes.
- TLS endpoint isolation: If upgrading is delayed, separate Erlang TLS endpoints from internally trusted network segments to limit blast radius from external attackers.
2. Patch/Upgrade Steps:
- Verify current OTP version:
erl -eval 'io:format("~p~n", [erlang:system_info(otp_release)]), halt().' -noshell - Upgrade to patched version:
- Source-based: Download OTP 27.3.4.15 / 28.5.0.4 / 29.0.4 from GitHub releases, compile, and deploy.
- Package manager: For Debian/Ubuntu, use Erlang Solutions apt repositories and pin to the patched release.
- Docker: Pull the patched
erlang:27.3.4.15/erlang:28.5.0.4/erlang:29.0.4images and rebuild.
- Restart BEAM nodes. Verify
erlang:system_info(otp_release)reflects the new version and that the ssl application version is ≥ 11.2.12.11 / 11.6.0.4 / 11.7.4 (checkapplication:get_key(ssl, vsn)).
3. Long-Term Hardening:
- Certificate chain validation: Enforce strict peer certificate validation (
verify_peer) with a curated CA bundle. While this does not prevent the recursion (the vulnerability triggers during chain reconstruction before validation completes), it reduces the attack surface for legitimate CAs that may accidentally issue cross-signed pairs. - BEAM process limits: Configure
+P(process limit) and+M(memory allocator) flags, and set processmax_heap_sizeinerlcommand-line options to cap per-process memory and force early crash rather than node-wide OOM. - Supervision strategy: Use
rest_for_oneorone_for_onesupervision trees with crash-rate limits (max_restarts/max_seconds) to ensure a crashed handler restarts rather than destabilizing the entire node. - Monitoring: Deploy BEAM VM memory monitoring (Prometheus
vm_memory,erlang_vm_process_count) with alerts on anomalous stack growth. - Network segmentation: Place Erlang TLS endpoints behind a WAF or TLS-terminating reverse proxy in production architectures.
References
- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2026-58227 — Official NVD record with vulnerability description and affected version details.
- OSV Advisory: https://osv.dev/vulnerability/CVE-2026-58227 — OSV database entry citing the vulnerability claim and patch references (single-source patch claim — treat patch confirmation with caution).
- Erlang/OTP GitHub Releases: https://github.com/erlang/otp/releases — Official release notes; verify patch availability in OTP 27.3.4.15, 28.5.0.4, and 29.0.4.
- Erlang Security Announcements: https://erlang.org/security — Official Erlang/OTP security advisory channel.
- CISA KEV Database: Not listed. No known exploitation-in-the-wild or threat actor campaigns have been publicly documented for CVE-2026-58227 as of this report's publication date. The EPSS score (0.00350, 27.7th percentile) confirms low current exploitation probability, but the trivial attack complexity and lack of required authentication make rapid exploitation likely once a public PoC emerges.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.