A 32-Year-Old Bug Walks Into A Telnet Server (GNU inetutils Telnetd CVE-2026-32746 Pre-Auth RCE)
A long, long time ago, in a land free of binary exploit mitigations, when Unix still roamed the Earth, there lived a pre-authentication Telnetd vulnerability.
In fact, this vulnerability was born so long ago (way back in 1994) that it may even be older than you. To put the timespan in perspective: it came into existence the same year the seminal movie Hackers was released.
That was so long ago that RISC was still a distant dream.
Come to think of it, maybe it was even the product of Zero Cool himself?

Anyway. Recently, this vulnerability was brutally put to rest.
What Are We Looking At Here?
If you're not familiar with Telnet, that's okay.
Telnet is a network protocol that provides a command-line interface for communicating with a remote server over TCP/IP. In other words, remote code execution as a service. Typical setups do have an authentication barrier, requiring you to log in before you can access the system's shell. It also operates over plaintext, which means yes, it transmits your username and password across the network in the clear.
The de facto replacement these days is SSH, and Telnet is becoming increasingly uncommon.
What Is CVE-2026-32746?
CVE-2026-32746, discovered by the DREAM Security Research Team, is a BSS-based buffer overflow that allows an attacker to corrupt roughly 400 bytes of adjacent variables.
It resides in the LINEMODE SLC (Set Linemode Characters) negotiation handler. While strictly speaking it affects 'just' GNU inetutils, most vendors have based their Telnetd implementations on the same code, making the blast radius vast and somewhat difficult to estimate. It definitely includes all the major Linux distributions (we checked).
With a vulnerability like this, we expected the Internet to explode with excitement - yet it’s been almost a week now with no good analysis. We thought we might as well publish where we got to.
We’ll go through a few things - how we isolated the vulnerability, what it enables attackers to do (and under what circumstances), and we’ll talk about why this particular vulnerability is more of a Pandora's box to exploit than you might think.
But let's start with the obvious question, which we're sure is on the lips of everyone living in a magical Unicorn land where legacy technologies simply don't exist: why use Telnet in the first place?!
What’s Affected?
Well, this is a tricky one. The patch was applied to inetutils-telnetd, but many forks exist, and changes have been made throughout the years, copying and pasting this vulnerability from system to system.
We have identified this CVE in at least the following:
- inetutils-telnetd itself
- Ubuntu
- Debian
- FreeBSD 13 / FreeBSD 15 Port
- NetBSD 10.1
- Citrix NetScaler
- Apple Mac Tahoe
- Haiku
- TrueNAS Core
- uCLinux
- libmtev
- DragonFlyBSD

It’s 2026, Why Telnet? Where Is The MCP?
Telnet has been around since the dawn of time. Many of you will be screaming at your screen right now - ‘who would use such an insecure protocol?!’.
Well, as some of you may be surprised to learn, the venerable Telnet is still very much present on production systems, for a surprisingly wide variety of reasons. Maybe it's the only thing the vendor supports ('This CNC machine costs $X thousand a minute in downtime if it breaks, and you want to add... what?! An SSH client?! Dude, it runs on an 8-bit microcontroller!'). Maybe there's some deeply technical reason migration isn't possible.
The fact remains: people still run it, as evidenced by its strong presence in the repositories of every major distribution. It has truly stood the test of time.

A Vulnerability In Telnet?! Isn't Telnet Just, Like, The Same As Netcat?
Some of our readers, blissfully unaware, may be under the impression that Telnet is simply a TCP stream at the protocol level. Indeed, some implementations are exactly that: a TCP socket connected to a shell. Simple, impossible (?) to break.
This, however, is not the case. Telnet supports a range of features: terminal control (want to turn on echoing? turn it off?), client window size negotiation, authentication, and even encryption. We're sure that somewhere, some poor soul is tasked with maintaining enterprise security across all of these features.
As everyone knows, 'more features' means 'more attack surface'. Everyone remembers CVE-2026-24061, right? In that bug, a Telnet protocol feature intended to share environment variables with the server could be abused for RCE. Pretty painful, and less far-reaching than today's vulnerability, though considerably easier to exploit.
This particular vulnerability resides in the 'LINEMODE' feature of the Telnet protocol. As RFC 1184 puts it:
While in Linemode with editing enabled for the local side, network traffic is reduced to a couple of packets per command line, rather than a couple of packets per character typed. This is very useful for long delay networks, because the user has local response time while typing the command line, and only incurs the network delays after the command is typed. It is also useful to reduce costs on networks that charge on a per packet basis...
Yes, the vulnerability is so old, it dates from a time when networks charged on a ‘per-packet basis’.
The real details of the feature itself aren’t super-important to us (our priority is simply ‘hack all the things’). However, to get to the vulnerable code, we’ll need to know how to enable it, which means we need to learn a little about how Telnet negotiates connection parameters.
Tense Negotiations
For interoperability, the Telnet client and server won't enable these fancy options by default. When a connection is first established, some in-band signaling takes place (ho ho ho, whenever did that go wrong) via the IAC, or 'Interpret As Command', byte, defined as 0xFF.
There’s a whole bunch of things that can be negotiated, like local echo, for example, or the speed of your teletype (remember those? We don’t). As previously alluded to, however, the feature we’re interested in is the ‘LINEMODE’ option.
One of the things defined by this feature, named SLC (or ‘Set Linemode Characters’), is particularly interesting. It enables the server to communicate with the client and inform it that certain special features - whizz-bang new technology like ‘backspace’, for example - should be represented by specific control codes.
To zoom in a little, let’s take a look at a hypothetical negotiation. First, we connect to a Telnet server via TCP. The server immediately sends the following data:
IAC DO LINEMODE (or 0xFF 0xFD 0x22, for those that prefer hex)
Here, the ‘DO’ is indicating that the server is requesting the capability. To enable it, the client responds with a ‘WILL’:
IAC WILL LINEMODE (0xFF 0xFB 0x22)
Once that’s sorted, the server sends a list of three-byte triplets, each indicating a special character to be replaced, the ‘support level’, and the actual character value. The client can then take a good look, decide if it wants to modify any, and if so, send a reply containing new values - again, a list of three-byte triplets.
IAC SB LINEMODE LM_SLC <triplets> IAC SE (0xFF 0xFA 0x03 <triplets> 0xFF 0xF0)
The server will duly store all these values in a global array of a fixed size, without doing any bounds checking. Wait, what?!
Yes, that’s the vulnerability. Undetected since 1994, people. The patch is as close to modern art as information security will ever get.

But wait! It gets even ‘funnier’!
What could be funnier, you ask?
Well, what if exactly the same vulnerability was present in the Telnet client, rather than the server, way back in 2005?
Yes, it’s true, folks. CVE-2005-0469 is this vulnerability’s doppelganger - essentially the same, but on the client side, where a function named slc_add_reply was missing a bounds check. The fix is an identical bounds check patch to today’s vulnerability.
Thankfully, twenty years later, somebody thought to check the server end for the same vulnerability.
They say history doesn't repeat, but it sure does rhyme.

On To Exploitation
Of course, as many of our readers know, this isn’t the end of the story - nay, this is merely the beginning of our odyssey of pain.
- Yes, it’s a new vulnerability.
- Yes, it’s a CVSS three squillion.
But can baddies actually exploit it to do something useful?
Well. That’s the question we’re here to answer.
Unfortunately, though, the answer is somewhat muddy and requires a little bit of nuance. Yes, we can overflow a global variable with data we control (and thus corrupt the memory locations that follow it). But that’s where the happy days end, and the real world sets in.
Firstly, the data we can send to the server is somewhat limited. As mentioned before, it is in the form of triplets: a function, a flag, and a value, each 1 byte long. Each of these has its own restrictions, mostly found in the process_slc function.
Let’s take a look at it.
void
process_slc (register unsigned char func, register unsigned char flag,
register cc_t val)
{
register int hislevel, mylevel, ack;
/*
* Ensure that we know something about this function
*/
if (func > NSLC)
{
add_slc (func, SLC_NOSUPPORT, 0);
return;
}
Here’s our first restriction - if the func byte is greater than the NSLC constant (which comes to 0x1e), then the rest of the triplet will be discarded. While the first byte makes it through unscathed, the remaining bytes are set to SLC_NOSUPPORT (which is zero) and zero itself. This triplet is then added to the global variable via add_slc.
Not ideal, but we can work with it, right?
What’s the rest of the function look like?
/*
* Process the special case requests of 0 SLC_DEFAULT 0
* and 0 SLC_VARIABLE 0. Be a little forgiving here, don't
* worry about whether the value is actually 0 or not.
*/
if (func == 0)
{
if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT)
{
default_slc ();
send_slc ();
}
else if (flag == SLC_VARIABLE)
{
send_slc ();
}
return;
}
Ah. This is also somewhat troublesome - if the function is zero, then our triplet also doesn’t make it to the global buffer. Hm. What about the rest of the triplet, though? Surely they don’t also have similar constraints?
Well, the good news is that the process_slc function gives us no more trouble. However, it does hand off to change_slc, which does some further mutilation of our formerly so nice triplets.
Intended to transform the values sent by the client, based on the server’s capabilities, the server will perform some modifications before accepting the SLC:
hislevel = flag & SLC_LEVELBITS;
mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
/*
* If client is setting a function to NOSUPPORT
* or DEFAULT, then we can easily and directly
* accomodate the request.
*/
if (hislevel == SLC_NOSUPPORT)
{
slctab[func].current.flag = flag;
slctab[func].current.val = (cc_t) _POSIX_VDISABLE;
flag |= SLC_ACK;
add_slc (func, flag, val);
return;
}
What’s going on here?! Well, the server is taking the bottom two bits of the ‘flag’ - the second byte in our triplet - and using this to set ‘hislevel’. This indicates the level of support that the client has (who, it seems, the Telnet server has determined to be male). If this is SLC_NOSUPPORT - zero - then the flag has SLC_ACK (0x80) set, and is added to the SLC array.
The end result is that if the bottom two bits of the flag byte are zero, the top bit is set.
Hm.
0xFF, too, get special handling - a blessing or a curse, depending on what is needed at that particular point. As you can see, each byte in the triplet is checked, and if it is found to be 0xff, then it is doubled to 0xff 0xff. This enables us to expand our triplet from 3 to 4, 5, or even 6 bytes.
This has a critical consequence for the exploitability of the vulnerability.
if ((*slcptr++ = (unsigned char) func) == 0xff)
*slcptr++ = 0xff;
if ((*slcptr++ = (unsigned char) flag) == 0xff)
*slcptr++ = 0xff;
if ((*slcptr++ = (unsigned char) val) == 0xff)
*slcptr++ = 0xff;
This does prevent us from sneaking in an odd number of consecutive 0xff bytes - we can’t represent 0x11 0xff 0x22 , although we can represent 0x11 0xff 0xff 0x22 or even 0x11 0xff 0xff 0xff 0xff 0x22 . This is a major hurdle, particularly on 64-bit x86 systems, which often have repeating 0xff bytes in specific positions.
However, this cloud does come with a silver lining: alignment. Since each of the three bytes in a triplet has a different set of constraints, we can pad the buffer with 0xff to align our triplets slightly differently, and maybe - just maybe! - squeeze the data we need into the place we like it.
| 0xFF In | Triplet size | Bytes written | Alignment shift |
|---|---|---|---|
| None | 3 | [F, flag, V] |
+0 |
| func | 4 | [0xFF, 0xFF, flag, V] |
+1 |
| val | 4 | [F, flag, 0xFF, 0xFF] |
+1 |
| func + val | 5 | [0xFF, 0xFF, flag, 0xFF, 0xFF] |
+2 |
This technique comes in very useful when trying to align a particular func, flag or val inside a particular offset within an adjacent variable.
For example, the val byte could be aligned to overwrite the least significant byte (LSB) of a pointer for a partial overwrite.
From there, the code becomes a little more difficult to explain so succinctly, but the end result is that we can be assured that a fair amount of ingenuity is required to find malicious inputs that meet all the requirements.
AND THEN THINGS GET EVEN HARDER.
The data that we send must fit into a single Telnet ‘subnegotiation’ packet, which is 0x200 bytes. The slcbuf variable itself, which we overflow, is sized at 0x6C bytes. It already contains four header bytes, which is fortunate, but this restricts us to overwriting the immediate 0x190 bytes.
It does seem like a lot, but let’s see what that gets us.
What We Tried
From here on, everything is specific to a particular Telnetd binary. With each compilation, the compiler places global variables as it sees fit, meaning that global variables that fall within our window of overwriting on one system may differ on another system. We invested some time reviewing implementations we had to hand.
What we found was somewhat interesting, although also a harsh dose of reality. It’s worth noting upfront that we didn’t find a direct route to exploitation on any of the systems we observed, though we did observe varying degrees of exposure. We also found that exploitation on 64-bit x86 systems was significantly more difficult than on other systems due to the constraints we’ve enumerated above.
For example, on 64-bit systems, pointers typically have many consecutive NULL bytes, such as 0x0000000802215180 . In this case, to perform a full overwrite of the pointer, we need to write 3 consecutive NULL bytes, which is not possible as no aligned func/flag/val allows us to write this. Therefore, the only way to overwrite a pointer on 64-bit systems is to do a partial overwrite when targeting little-endian.
In other cases of Telnetd being compiled, the adjacent variables within the overwrite range had no security impact, either they changed a value that never gets used, or the value was overwritten by the server before being used.
Rather than try to explain the relative vulnerability of each OS, we’ll stick to the one that seemed the most interesting - although it is somewhat vintage.
Debian - 32bit Edition
After some difficulty attempting to exploit a 64-bit x86 system for RCE [not pictured], we started to wonder - perhaps a lot of the legacy systems that run Telnet are of the 32bit x86 variety. Would exploitation be more convenient on those?
We turned to Debian - which interestingly, dropped support for 32bit x86 systems some time ago, meaning this vulnerability is forever - and installed bookworm, a relatively old version, but the newest to support a 32bit environment. We threw the Telnetd binary into our favourite disassembler, and found that things were much more interesting.

IDA Disassembly of slcbuf and adjacent variables
Here you can see the slcbuf variable, which we can overflow, and a handful of variables following it (there are more not shown above - rest assured, they are irrelevant for our purposes). There’s slcptr - a pointer into the slcbuf - and then slcchange, a relatively boring boolean. After a length variable, there’s an innocent-looking variable named def_slcbuf. Let’s take a look at the source and see what this variable does.
void do_opt_slc (unsigned char *ptr, int len)
{
...
if (terminit ())
{
/* actual processing logic omitted */
}
else
{
/*
* save this slc buffer if it is the first, otherwise dump
* it.
*/
if (def_slcbuf == (unsigned char *) 0)
{
def_slclen = len;
def_slcbuf = (unsigned char *) malloc ((unsigned) len);
if (def_slcbuf == (unsigned char *) 0)
return; /* too bad */
memmove (def_slcbuf, ptr, len);
}
}
}
void deferslc (void)
{
if (def_slcbuf)
{
start_slc (1);
do_opt_slc (def_slcbuf, def_slclen);
end_slc (0);
free (def_slcbuf);
def_slcbuf = (unsigned char *) 0;
def_slclen = 0;
}
}
Well, it's pretty obvious (or maybe we’ve just been staring at this codebase too long?). If terminit isn’t set when the SLC triplets are received, no actual processing is done - rather, the def_slcbuf buffer is allocated (via malloc), and the packet is copied into it. Later on, once terminit is satisfied and the terminal is initialised, deferslc is invoked, which then does the processing ‘for real’, and releases the def_slcbuf via free.
Sounds fairly mundane, right?
Well, actually, it’s not - it’s a gateway to [almost] exploitation.
Our first step is triggering this ‘defer’ behavior in the first place. To do this is straightforward - when the server advertises supported features, we can simply send a response to the LINEMODE feature before we send a response to the TTYPE feature. Once the server receives the TTYPE data, it will consider terminal initialisation complete, terminit will return true, the LINEMODE will be processed (including our overflow!), and finally, the def_slcbuf will be released via free.
[SERVER] ← IAC DO TTYPE
[SERVER] ← IAC DO LINEMODE
[CLIENT] → IAC WILL LINEMODE
[CLIENT] → IAC WILL TTYPE
[SERVER] ← IAC SB LINEMODE 0110 IAC SE
[SERVER] ← IAC SB TTYPE 01 IAC SE
[CLIENT] → IAC SB LINEMODE (…) IAC SE <save SLC into def_slcbuf>
[CLIENT] → IAC SB TTYPE (…) IAC SE <_terminit = 1, do_opt_slc(def_slcbuf)>
Aha, did you spot that? We snuck in the meat of our technique right under your nose, there. The def_slcbuf will be released via free. Since we control def_slcbuf - we overwrote it with SLC triplets - we can cause free to be invoked on any memory location we choose. This is a very powerful primitive.

Of course, exploitation from here on out depends heavily on the libc being used on the target. On many lighter embedded systems, this will quickly lead to RCE via an arbitrary write. On a Debian system, however - even one as outdated as the 12.13.0, which we were forced to use for 32bit support - the heap is less naive, and will perform a fair amount of checks on the data before actually unlinking chunks.
In a full-featured codebase, there would be a plentiful supply of function pointers conveniently located in heap chunks, just waiting to be overwritten. However, the Telnetd source is an artifact of a different time, and that shows in the coding style [please don’t come for us Unix greybeards, we love you]. Dynamic allocations are not something that are found often here, and when they are, they are defensively checked with a rigor unheard of by modern-day JavaScript engineers - perhaps this is part of why the code has survived for so long without requiring many additions.
However, as we noted earlier, complexity slowly creeps in with the protocol's more advanced functions. If you’re unlucky enough to maintain a Telnet server that uses Kerberos authentication - yes, that’s a real thing! - then the opportunities presented to attackers for exploitation are much more frequent. Even the complexity introduced by the libc may be enough for sufficiently skilled attackers to exploit to pry open the application.
This is a really good example of the nuance involved in this vulnerability. A seemingly benign choice made entirely at the whim of the compiler, run years ago, has just transformed our vulnerability from “huh that looks hard” to “oh wow, arbitrary free!” and pushed it a lot closer to the feature-complete status of RCE.
Detection Approaches
Here at watchTowr, we love providing complete end-to-end Detection Artifact Generators for interested parties to use to prove the status of their own systems. This vulnerability, however, is not so simple - we’re bereft of a functional exploit for the systems we tested, and even if we had one, it would probably be worthless for any other systems.
We can, however, provide a detection artifact generator that performs almost the same thing. For this, we can leverage the ‘negotiation’ part of the process.
If you take another look at the patch above, you’ll see that it deals with an overflow condition in a very minimalist way - if the provided data would overrun the slcbuf buffer, it is simply ignored. This is effective and prevents exploitation, but it doesn’t give the client any feedback - if the server sent some kind of error message, or even terminated the connection, it would be trivial to detect, but alas, we don’t have that luxury here.
However, when we discussed negotiation earlier, we left out one relatively minor detail: once the client sends SLC data to the server, the server will respond by sending its own SLC list back to the client, generated from the client's requested inputs and merged with its own environment. Since the server will silently ignore everything that won’t fit in the buffer, we can simply send junk data to fill the buffer, followed by some unusual value. A vulnerable server will store the unusual data, even though it overflows the buffer, while a patched server will silently drop it. If we see the ‘unusual value’ in the response, we know the target is vulnerable.
There is one thing we need to point out before directing our beloved readership to our detection artifact generator. We have carefully engineered our detection artifact generator to perform the most minimal, non-invasive overflow, overwriting a single byte beyond slcbuf. It would take a truly unlucky individual, but it is possible that - if a server is indeed vulnerable - this wayward byte could cause a segfault, or possibly something even worse (the greybeards reading this post direct us to use our newfangled internet search engine to look up the term ‘nasal demons’ for an example of the possible consequences).
The server process is typically (we want to say ‘always’, but we’re not that dumb) spawned under the careful ownership of inetd , which means that even a segfault wouldn’t cause any visible harm - the Telnet session would drop, sure, but the daemon itself (and even other concurrent users) would not be affected.
Of course, all this logic assumes that the server even supports the LINEMODE feature. Many embedded applications are simple enough that they don’t provide this function. Some don’t even offer any form of negotiation. It’s a good ‘first test’ to very quickly assess the exposure of an estate - sure, the CNC shop floor looks terrifying when you see 200 hosts with Telnet open, but if all they do is pipe to some dodgy C app, they’re not going to be exposed to this particular vulnerability (although we’re sure they have some nice vulnerabilitys all of their own).
For these two reasons, we’ve equipped the Detection Artifact Generator with a simple ‘probe mode’ in addition to the ability to actually overflow the target buffer. This ‘probe mode’ will simply connect to a server and wait to see if the LINEMODE feature is advertised. It will then print a message indicating if the feature is enabled, and immediately exit, without sending any overflow attempt to the target. This should be enough to placate even the wobbliest of Telnet-sporting antique industrial machinery (but we’re still not paying to fix it if it catches fire).
To demonstrate, here’s a screenshot of the test in action, detecting a vulnerable 32bit x86 Debian install:

For the techies who want to know what’s happening under the hood, run the script with --verbose and see the underlying bytes:
python3 watchtowr-vs-Telnetd-CVE-2026-32746.py --rhost 192.168.0.154 --verbose
...
[#] Triggering overflow with SLC subnegotiation...
[>] IAC SB LINEMODE (
010041 010041 010041 010041 010041 010041
010041 010041 010041 010041 010041 010041
010041 010041 010041 010041 010041 010041
010041 010041 010041 010041 010041 010041
010041 010041 010041 010041 010041 010041
010041 010041 010041 010041
) IAC SE
...
[<] IAC SB LINEMODE (
03
018041 018041 018041 018041 018041 018041
018041 018041 018041 018041 018041 018041
018041 018041 018041 018041 018041 018041
018041 018041 01800d 0a4c69 6e7578 20362e
312e30 2d3434 2d3638 362d70 616520 286465
626961 6e3131 292028 707473 2f3129 0d0a0d
0a6465 626961 6e3131 206c6f 67696e 3a20
) IAC SE
...
--------------------
[+] LINEMODE is supported
[!] Telnetd vulnerable
You can see here that we’ve sent a large SLC table, enough to just slightly overflow the target buffer. Note, however, that something unexpected has happened - rather than the SLC table we expect to see returned, we see lots of random-looking bytes returned. That’s not even what we sent! What’s gone on here?!
This is a good example of the ‘nasal demons’ to which the greybeards alluded. We’ve hit a different codepath, causing internal values to be added to the SLC table.
Other commonly-seen behaviors include returning heap pointers in the place of SLC data (usually because the slcptr global has been overwritten). This is another very useful primitive, and something that attackers will find invaluable in building exploits:

$ python3 watchTowr-vs-Telnetd-CVE-2026-32746-leak.py --rhost 192.168.0.154
[+] Leaked Heap slcptr: 0x004b1a38
[+] Leaked Heap slcptr: 0x00468a38
[+] Leaked Heap slcptr: 0x004f4a38
[+] Leaked Heap slcptr: 0x00478a38
As we say, this is specific to the binary on the system. A further demonstration of the complexity involved in successful exploitation of the (extremely diverse) install base of Telnetd.
Conclusion
Well, we haven’t achieved the coveted RCE, although we’ve discovered a huge amount of probably-not-ideal behavior, such as our nice arbitrary free alongside a pointer leak. We’d love to have spent more time on this vulnerability, analysing more and more builds of Telnetd, but unfortunately, no one lives forever, and we all have other things to do.
The most striking thing about this vulnerability is its sheer reach. A good portion of the huge number of systems running some kind of Telnet server includes this vulnerable code. It’s been around forever - heck, Kurt Cobain was still alive when this hole was introduced! - so it’s had plenty of time to worm its way into all the nooks and crannies of any network worth caring about.
We’re convinced that instances of this specimen are going to crop up for years to come.
The other interesting property is that, in stark contrast to the homogeneous install base of, say, an SSLVPN appliance, or even an operating system, there are countless builds of a myriad of codebases that have included this blunder.
Given the class of the vulnerability - memory corruption - any successful exploit is required to be tailored to the environment that the target runs on.
This is good news for most of us, who are not targeted by large, well-equipped organisations. While it’s somewhat easy for us to check if our office TV is vulnerable (spoiler: it’s not), it’s unlikely anyone will invest the time and effort into crafting a functional exploit for it. This, however, is unlikely to comfort those defenders who are maintaining the sort of equipment that requires a Telnet daemon, and who may well be in the sights of exactly that class of attacker.
There is, of course, always a chance that a popular product will be found to sport a memory layout just right for clean exploitation, and if an exploit for that goes public - well, all bets are off. But then there is a somewhat limited overlap between people who use such mainstream equipment and those who really need to accept untrusted (or any, really) Telnet traffic.
Of course, the real answer here is ‘patch immediately, especially if downtime is so expensive that you can’t afford to take the machine down to patch it’. While we’d love to give out the version number of patched software, this simply isn’t possible, for two reasons (one much more sensible than the other).
Given the breadth of affected software, this would be a little redundant; anything based on a vulnerable version of inetutils is affected, which is a list far too long to enumerate.
Shamefully, the inetutils project hasn’t actually released a fixed version of their software (at least at the time of publishing). The newest version available for download - 2.7 - is still vulnerable. You’ll need to make sure you clone a fixed commit from git (this one or newer) and build from source.
Following on from this slothful lead - or rather, the lack of any real security response - most Linux distributions have not yet shipped packages.
Who can blame them? If the maintainers don’t think it’s important enough to justify a release, it must be minor, right?

At the time of writing, only the sid/forky track carries a fix - every other Debian release remains vulnerable.
The research published by watchTowr Labs is just a glimpse into what powers the watchTowr Platform – delivering automated, continuous testing against real attacker behaviour.
By combining Proactive Threat Intelligence and External Attack Surface Management into a single Preemptive Exposure Management capability, the watchTowr Platform helps organisations rapidly react to emerging threats – and gives them what matters most: time to respond.