>Any service using Erlang/OTP's SSH library for remote access such as those used in OT/IoT devices, edge computing devices are susceptible to exploitation.
https://thehackernews.com/2025/04/critical-erlangotp-ssh-vul...
>Any service using Erlang/OTP's SSH library for remote access such as those used in OT/IoT devices, edge computing devices are susceptible to exploitation.
https://thehackernews.com/2025/04/critical-erlangotp-ssh-vul...
See for example https://blog.differentpla.net/blog/2022/11/01/erlang-ssh/
Of course, easy protocol parsing doesn't do the whole job; state management is required too (and was missed here, clearly).
There's some value in avoiding a monoculture, or choosing different trade-offs (e.g. binary size, memory usage). But as exemplified by this incident, any incentives must be carefully weighted against the risks. SSH is your final line of defence.
This is an Erlang daemon, thus written in a managed language without buffer overflows,etc, but it seems like someone left a huge gaping logic hole to drive a bus through. SSH or not, this could've equally well been a logic hole in a base webserver,etc.
I'd say this is more akin to the Log4j debacle, a perfectly safe language but bad design makes it vulnerable to something trivial.
The BEAM is also more or less an abstraction around an event loop for async i/o. If you want async i/o in nifs, I think you want to integrate with BEAM's event loop. Inside NIFs, I think you want to use enif_select [1] (and friends), available since OTP 20 originally from 2017-06-21. In a port driver, you'd use driver_select [2] which I think has been around forever --- there's mentions of changes in R13 which I think was mostly release 2009-11-20 (that may have been R13B though).
[1] https://www.erlang.org/doc/apps/erts/erl_nif.html#enif_selec...
[2] https://www.erlang.org/doc/apps/erts/erl_driver.html#driver_...
When we (or at least some quantity of “we”) want is infrequent native calls to be able to fail without taking the BEAM down.
The problem with doing it with threads though is that a bad thread can still vomit all over working memory, still causing a panic even if it itself doesn’t panic.
a) run the native code as a separate process; either a port program, a c-node, or just a regular program that you interact with via some interprocess communication (sockets, pipes, signals, a shared filesystem, shared memory segments if you're brave)
b) some sort of sandybox thing; like compile to wasm and then jit back to (hopefully) safe native.
c) just run the native code, it's probably fine, hopefully. My experience with NIFs is that they are usually very short code that should be easy to review, so this isn't as bad as it sounds...
If your native code is short, option c is probably fine; if your native code is long, option a makes more sense. If you want to make things harder without real justification, b sounds good :P
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=OpenSSH
It's true that there are 5 advisories so far in this year alone, but let's consider the actual impact:
CVE-2025-32728 - Error in documentation, possibly leading to misconfiguration
CVE-2025-30095 - Debian+dropbear-specific
CVE-2025-27731 - Windows-specific; local privilege escalation; OpenSSH doesn't target/support Windows
CVE-2025-26466 - Remote DoS
CVE-2025-26465 - MitM involving host key DNS verification; high attack complexity (relies on exhausting client memory)
OpenBSD enables sshd(8) in the default install, and has so far had two RCEs in 30 years. Now, not everyone runs OpenBSD, but I'd personally throw the stones at e.g. Debian (see CVE-2008-0166).While what is easier for those of us not working on the beam is to put the glitchy code into its own service and put up with the maintenance overhead.
But when you have one or two solutions the friction to move to three becomes difficult. People start talking about how having dozens will be chaos. While true, sometimes you really do just need three and it’s not a slippery slope.
Only OpenSSL had heartbleed. No other implementation of TLS protocols was affected. Many systems integrate with OpenSSL's protocol code, but there's also several that do their own protocol work and use ciphers from OpenSSL (and some that do both).
Erlang's ssl implementation at the time of heartbleed wasn't anywhere close in throughput to using OpenSSL separately. If I'm remembering right, OTP 18 (June 2015) is when it got good enough that it made more sense to run an Erlang https server without a separate TLS termination daemon. Heartbleed became known April 2014, so Erlang SSL was too late to help there, really. More secure, but unusable wirh load doesn't help much.
Also, Erlang SSL was one of many implementations thst needed to be reminded of 1998 era security issues in 2017. [1]