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
On Fri, Mar 13, 2026 at 01:19:49PM +0000, Stuart Henderson wrote: On 2026/03/13 06:37, Justin Swartz wrote: OpenBSD 7.8 [PARTIAL LEAKAGE] The client blocks most variables which have not been explicitly exported, but potentially sensitive variables such as DISPLAY, XAUTHORITY and PRINTER are leaked without prior export. ha, we've had that for a long time.
--------------------- Date: 2005/02/27 15:46:42 Author: otto Branch: HEAD Tag: OPENBSD37BASE Log: - only send exported vars (based on a diff from Solar Designer) - fix some buffer overflows (also some Solar Designer input)
ok deraadt@ cloder@
Members: authenc.c:1.6->1.7 commands.c:1.47->1.48 externs.h:1.13->1.14 telnet.c:1.18->1.19 --------------------- Oh, I didn't recall.
Looking at this now:
https://cvsweb.openbsd.org/src/usr.bin/telnet
I see that these exports are explicit in commands.c:
envexport("DISPLAY"); envexport("PRINTER"); envexport("XAUTHORITY");
Also, there's support for the TERMINAL-TYPE (RFC 1091) and X-DISPLAY-LOCATION (RFC 1096) telnet protocol options in telnet.c, which would send TERM and DISPLAY even if these are not exported.
Looking at RHEL 9 telnet-0.17-85.el9's telnet-0.17-env.patch against Linux NetKit, I see it also deliberately allows TERM and DISPLAY to be sent via these protocol options even if not exported.
Perhaps these default exports once made sense, but not anymore... except maybe for TERM, which still needs to work out of the box?
I also found there's OpenBSD-derived telnet-bsd package in Gentoo (client and server) and OpenWrt (client only), originally ported by Thorsten Kukuk of SUSE. I didn't check when it was forked, nor whether it already contains the 2005 fixes mentioned above or equivalent. Someone (perhaps involved with those distros) could want to check.
Alexander