On Tue, Feb 24, 2026 at 06:29:43AM +0100, Solar Designer wrote: On Tue, Feb 24, 2026 at 03:17:02AM +0200, Justin Swartz wrote: In my opinion, to fix this issue and finally put the ghost of CVE-1999-0073 to rest: telnetd must drop the blacklist approach and adopt the OpenSSH AcceptEnv-style approach suggested by Simon Josefsson [1], which amounts to preparing a brand new environment for /bin/login based on a strict whitelist of variables names considered to be "safe", and perhaps a healthy dose of input sanitization for their respective values. Oh, sure. A couple of decades ago I ported OpenBSD's telnet and telnetd to Linux for our distro, Owl. I no longer recalled all detail, but looking at my "Linux port" patch now, it appears to implement a strict allow-list approach already. There's a comment saying the "list comes from Linux NetKit telnetd, version 0.17", so maybe NetKit already used that approach too, and Linux distros got a regression by switching from NetKit to InetUtils? Or it could be that Red Hat used NetKit and Debian went with InetUtils. I see I'm also lightly sanitizing env var values (only for not containing '/' and being of sane length), which I doubt was in NetKit. I'm now looking at telnet-0.17-85.el9.src.rpm from Rocky Linux 9. The telnet server part of it is still based on NetKit 0.17, where the latest ChangeLog entry is:
22-Jul-2000: Bug fixes for environment processing from Olaf Kirch. Also fixes privacy issue noticed by Steve Bellovin. Also fix a wrong assert().
and the code is:
/ check that variable is safe to pass to login or shell / #if 0 / insecure version / static int envvarok(char varp) { if (strncmp(varp, "LD", strlen("LD")) && strncmp(varp, "ELFLD", strlen("ELFLD")) && strncmp(varp, "AOUTLD", strlen("AOUTLD")) && strncmp(varp, "RLD", strlen("RLD")) && strcmp(varp, "LIBPATH") && strcmp(varp, "ENV") && strcmp(varp, "IFS")) { return 1; } else { / optionally syslog(LOGINFO) here / return 0; } }
#else static int envvarok(char varp) { / Allow only these variables. / if (!strcmp(varp, "TERM")) return 1; if (!strcmp(varp, "DISPLAY")) return 1; if (!strcmp(varp, "USER")) return 1; if (!strcmp(varp, "LOGNAME")) return 1; if (!strcmp(varp, "POSIXLYCORRECT")) return 1;
/ optionally syslog(LOGINFO) here / return 0; }
In my patch against OpenBSD's it is:
+/ This list comes from Linux NetKit telnetd, version 0.17 / +static char goodenvtable[] = { + "TERM", + "DISPLAY", + "USER", + "LOGNAME", + "POSIXLYCORRECT", + NULL };
[...]
+envvarok(varp, valp) + char varp, valp; { [...] + for (i = 0; goodenvtable[i]; i++) { + if (strcmp(goodenvtable[i], varp)) + continue; + if (strchr(valp, '/') || strlen(valp) >= 0x100) { + syslog(LOGNOTICE, "Rejected attempt to set the " + "environment variable \"%s\" to an " + "invalid value", varp); + return (0); + } + return (1); + } [...] + return (0);
So it looks like in the Linux world non-use of an allow list is specific to InetUtils, which means primarily Debian and derived distros.
Alexander