Between March 1 and March 29, 2023, researchers at Phylum, Check Point, and ReversingLabs catalogued more than 450 malicious Python packages uploaded to PyPI, a rate of roughly 15 per day during active periods. The vast majority were variants of the W4SP stealer family, which harvests Discord tokens, browser credentials, and cryptocurrency wallet files, then exfiltrates them to attacker-controlled Discord webhooks. By late May, sustained abuse would push PyPI to temporarily halt new user and project registration, the first such administrative pause in the index's history. The March wave is the clearest single-month data point we have for how commodity Python malware actually reaches developer workstations, and it reveals weaknesses in both PyPI's moderation model and enterprise install hygiene.
What made these packages harmful?
These packages were harmful because they executed obfuscated payloads during installation through setup.py, running arbitrary code with the privileges of the developer running pip install. The typical pattern used a multi-layer Fernet or base85 string, decoded at install time, that pulled a second-stage blank grabber or creal stealer binary from a paste site or GitHub gist. Common names that month included colorama-utils, typing-util, request-check, and pyrequests-util, all typosquats of real packages. Once the payload ran, it would scan AppData for Discord's local storage, copy Login Data from Chrome and Edge, and POST the archive to a webhook URL hard-coded in the payload.
# Reconstructed install-time trigger (simplified)
from setuptools import setup
import base64, os
exec(base64.b64decode(b'aW1wb3J0IHVybGxpYi5yZXF1ZXN0...'))
setup(name='colorama-utils', version='0.0.3')
Who was running the campaign?
The campaign was run primarily by a loose cluster Phylum tracks as Kekw and a separate group using the alias "lolip0p", both publishing dozens of packages per day across churned accounts. Check Point's March 9, 2023 report on three packages from the user lolip0p showed the same Discord C2 infrastructure across 32 sibling uploads. The actors registered throwaway Gmail addresses, created accounts, and published packages within minutes, relying on the fact that PyPI applied little automated static analysis to new uploads at the time. A handful of samples reused wallet-stealing code from WASP v5.0, which had been sold on underground forums for about $20 since late 2022.
Why did typosquatting work so reliably?
Typosquatting worked so reliably because PyPI's name-similarity checks were loose and because pip install offers no visual signal when a developer installs a 0-version-old package from an unknown publisher. The top-hit names followed four patterns: character swap (requsts for requests), plural (colorams for colorama), suffix (typing-util for typing), and utility framing (pyrequests-util). Roughly 38% of the March malicious packages imitated a package in the top 5,000 by download volume, which maximizes the probability that a typo-prone developer would land there. None of the top-5,000 owners had reserved their typosquat namespace, because PyPI has no namespace reservation API.
How effective was PyPI's response?
PyPI's response during March was reactive and human-driven: admins removed reported packages within hours, but the index lacked automated pre-publish static scanning, so new uploads continued to slip through. OpenSSF's package-analysis project had been running a pilot feed throughout 2022, but results were not yet integrated into PyPI's moderation pipeline. By May 20, sustained abuse led PyPI to pause new user and project registration for three days. Later in 2023, PyPI rolled out mandatory 2FA for project maintainers of the top 1% of projects by download volume, funded partly by an AWS open-source grant. The March wave was the data point that justified the 2FA push internally.
What can defenders do on the install side?
Defenders can enforce install-time policy by pinning dependencies with hashes, resolving against an internal mirror that runs malware scanning on ingestion, and disabling setup.py execution in favor of PEP 517 build backends where practical. A conservative baseline is to require pip install --require-hashes -r requirements.txt in CI, maintain a private mirror (Artifactory, Nexus, or a simple Bandersnatch), and gate the mirror on a malicious-package feed such as OSV.dev, PyPA's advisory database, or commercial vendors. Teams that run developer workstations on unprivileged accounts and block outbound Discord webhooks at the egress layer materially limit the damage even if a malicious install succeeds.
How do you triage an install-time compromise?
Triage starts with the filesystem artifacts the stealer leaves behind, specifically temp-directory archives, unexpected Python subprocesses spawned from pip, and outbound connections to discord.com/api/webhooks. Hunt queries should pull command lines containing setup.py install, process trees where pip invoked python which invoked curl or powershell, and any Chromium Login Data file copies in the past 30 days. If you find a hit, rotate every credential the browser could have cached, kill and reissue any Discord tokens, and check for 2FA push acceptance in the same window, because several March samples also attempted Discord MFA bypass via nearby-login prompts.
How Safeguard Helps
Safeguard ingests PyPI publishing metadata and cross-references package signals, like newly published maintainers, suspicious setup.py patterns, and typosquat similarity to the top 5,000 names, against your SBOM in real time. Griffin AI explains why a specific package looks like W4SP or a typosquat of colorama, and produces a remediation plan that patches requirements.txt and updates the internal mirror's denylist. The TPRM view flags open-source dependencies imported transitively through a mid-tier SaaS supplier. Policy gates block any CI run that tries to resolve a flagged package, and reachability analysis tells you whether the malicious code was ever loaded by a shipped application, not just present in a dev lock file. The net effect is that install-time stealers no longer reach production or developer laptops unnoticed.