# PYTHON-LANG-SEC-064: telnetlib Usage Detected

> **Severity:** HIGH | **CWE:** CWE-319 | **OWASP:** A02:2021

- **Language:** Python
- **Category:** Python Core
- **URL:** https://codepathfinder.dev/registry/python/lang/PYTHON-LANG-SEC-064
- **Detection:** `pathfinder scan --ruleset python/PYTHON-LANG-SEC-064 --project .`

## Description

telnetlib.Telnet() implements the Telnet protocol, a legacy remote terminal protocol
that transmits all data including usernames, passwords, commands, and command output
in plaintext over TCP. Telnet was deprecated in Python 3.11 and removed in Python 3.13
due to its security problems.

Any credentials used to authenticate to a Telnet service are transmitted in plaintext
and can be captured by any observer on the network. Commands executed via Telnet and
their output are also visible, potentially exposing sensitive system information.

SSH is the universally accepted secure replacement for Telnet. Python's paramiko library
provides a complete SSH client implementation that supports password and key-based
authentication, command execution, SFTP, and port forwarding.


## Vulnerable Code

```python
import requests as http_requests
import urllib.request
import ftplib
import telnetlib

# SEC-064: telnetlib
tn = telnetlib.Telnet("example.com", 23)
```

## Secure Code

```python
# INSECURE: telnetlib for remote access
# import telnetlib
# tn = telnetlib.Telnet("host.example.com")
# tn.read_until(b"login: ")
# tn.write(username.encode() + b"\n")

# SECURE: Use paramiko SSH for remote command execution
import paramiko

def execute_remote_command(host: str, username: str,
                           key_path: str, command: str) -> str:
    """Execute a command on a remote host via SSH."""
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.RejectPolicy())
    ssh.connect(host, username=username, key_filename=key_path)
    stdin, stdout, stderr = ssh.exec_command(command)
    output = stdout.read().decode()
    error = stderr.read().decode()
    ssh.close()
    if error:
        raise RuntimeError(f"Command failed: {error}")
    return output

# SECURE: Netmiko for network device automation (uses SSH)
# from netmiko import ConnectHandler
# device = ConnectHandler(device_type="cisco_ios", host=host,
#                         username=username, use_keys=True, key_file=key_path)

```

## Detection Rule (Python SDK)

```python
from rules.python_decorators import python_rule
from codepathfinder import calls, QueryType

class TelnetModule(QueryType):
    fqns = ["telnetlib"]


@python_rule(
    id="PYTHON-LANG-SEC-064",
    name="telnetlib Usage Detected",
    severity="HIGH",
    category="lang",
    cwe="CWE-319",
    tags="python,telnet,insecure-transport,plaintext,CWE-319",
    message="telnetlib transmits data in plaintext. Use SSH (paramiko) instead.",
    owasp="A02:2021",
)
def detect_telnet():
    """Detects telnetlib.Telnet usage."""
    return TelnetModule.method("Telnet")
```

## How to Fix

- Replace telnetlib with paramiko for SSH-based remote command execution on Linux/Unix systems.
- For network device automation (Cisco, Juniper, etc.), use netmiko or NAPALM which use SSH instead of Telnet.
- Use SSH key-based authentication instead of password-based authentication when connecting to remote systems.
- Disable Telnet on all managed network devices and require SSH-only access.
- Migrate any telnetlib-dependent code before upgrading to Python 3.13, where telnetlib has been removed.

## Security Implications

- **Plaintext Credential Transmission:** Telnet login username and password are transmitted in plaintext, one character at a
time due to Telnet's character-mode protocol. An attacker observing the TCP stream
can reassemble and read the complete credentials.

- **Session Hijacking:** The entire Telnet session (commands and output) is transmitted in plaintext. An
attacker who can intercept the TCP stream can inject arbitrary commands into the
session, capturing or modifying the remote system state.

- **Network Infrastructure Attack:** Routers, switches, and embedded devices that expose Telnet management interfaces
are particularly vulnerable. Python scripts automating network device management
via Telnet expose device credentials and configuration to network observers.

- **Deprecated API with Removal Risk:** telnetlib was deprecated in Python 3.11 and removed in Python 3.13. Code using
telnetlib will fail on Python 3.13+ and must be migrated regardless of the security
concern.


## FAQ

**Q: When was telnetlib deprecated and removed from Python?**

telnetlib was deprecated in Python 3.11 (released October 2022) with a planned removal.
It was removed in Python 3.13 (released October 2024). Code using telnetlib must be
migrated before upgrading to Python 3.13 or later.


**Q: Are there legitimate uses for Telnet in 2025?**

Legacy network infrastructure, some industrial control systems (ICS/OT), and certain
embedded devices may still expose only Telnet management interfaces. These represent
legacy integration requirements, not good practice. In all such cases, use a dedicated
VPN or SSH tunnel to isolate and encrypt Telnet traffic, and plan migration to SSH.


**Q: How does paramiko compare to telnetlib for automation?**

paramiko provides SSH (Secure Shell) which is the secure successor to Telnet. SSH
encrypts all traffic, supports key-based authentication, provides host key verification
to prevent MITM, and supports SFTP, port forwarding, and X11 forwarding. paramiko
implements the full SSH protocol in pure Python with optional C acceleration.


**Q: What is netmiko and when should I use it?**

netmiko is a Python library built on paramiko that simplifies SSH connections to
network devices (Cisco IOS, Juniper JunOS, Arista EOS, etc.). It handles device-
specific command modes, paging, and prompt detection. Use netmiko instead of
telnetlib for all network device automation tasks.


**Q: Can I use SSH for Telnet-only devices via a proxy?**

If a device only supports Telnet, use a dedicated terminal server or out-of-band
management device that accepts SSH and proxies to the device via Telnet over a
physically secured local network. This protects credentials on the network-accessible
portion while acknowledging the local Telnet limitation.


**Q: Does this rule apply to custom Telnet implementations not using telnetlib?**

This rule detects telnetlib.Telnet() usage. Custom Telnet implementations using
raw sockets have the same security risks but would be detected by other rules
(PYTHON-LANG-SEC-070 for socket bind, PYTHON-LANG-SEC-014 for reverse shell patterns).
Manual review of any code implementing Telnet-like protocols is recommended.


## References

- [CWE-319: Cleartext Transmission of Sensitive Information](https://cwe.mitre.org/data/definitions/319.html)
- [Python docs: telnetlib deprecated in 3.11](https://docs.python.org/3.11/library/telnetlib.html)
- [paramiko documentation](https://www.paramiko.org/)
- [OWASP Top 10 A02:2021 Cryptographic Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures/)
- [OWASP TLS Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html)

---

Source: https://codepathfinder.dev/registry/python/lang/PYTHON-LANG-SEC-064
Code Pathfinder — Open source, type-aware SAST with cross-file dataflow analysis
