Safeguard
Threat Intelligence

Malicious PyPI packages: common infiltration patterns

Real malicious PyPI package examples — typosquats, dependency confusion, hijacked maintainers, and crypto stealers — and how Safeguard catches them before install.

Vikram Iyer
Security Researcher
8 min read

In March 2024, PyPI's security team took an unprecedented step: they froze new user registrations and new project creation for roughly 10 hours after a flood of malware-laced packages hit the index faster than moderators could review them. It wasn't an isolated incident. Between typosquatted package names, hijacked maintainer accounts, and dependency confusion tricks, PyPI has become one of the most heavily targeted open-source registries in the world — and the attacks keep getting more convincing. Security teams at Socket.dev, Phylum, and ReversingLabs have spent the last few years cataloguing these campaigns, and the patterns repeat often enough that they're now predictable. This post walks through the five infiltration techniques that show up again and again in real malicious PyPI package examples — from the 2022 PyTorch dependency confusion attack to 2024's crypto-stealing "aiocpa" package — and what actually stops them before they reach a build pipeline.

What is typosquatting and how do attackers exploit it on PyPI?

Typosquatting works by publishing a malicious package under a name that looks like a popular one, betting that a developer will fat-finger a pip install command. It's the oldest trick in the PyPI threat book, and it still works because package names are cheap to register and nothing stops an attacker from claiming a near-miss. A well-documented example is "colourama," a 2019 typosquat of the widely used "colorama" terminal-coloring library. The malicious clone included legitimate colorama code so it would function normally, but it also dropped a Windows startup script that monitored the clipboard for cryptocurrency wallet addresses and silently swapped them for an attacker-controlled address. Similarly, "fabrice" impersonated the popular SSH automation library "fabric" and, once installed, downloaded and executed a second-stage payload that harvested AWS credentials from environment variables. These aren't sophisticated exploits — they rely entirely on human error at the command line, one missing or transposed letter in pip install. That's precisely why they remain a top infiltration vector years later: single-character typosquats of packages like requests, numpy, and django continue to surface on PyPI on a rolling basis, often within days of removal.

How does dependency confusion let malicious packages jump into private builds?

Dependency confusion works by publishing a public package with the same name as an internal, private package, tricking build tools into pulling the public (malicious) version instead. Security researcher Alex Birsan demonstrated the technique in February 2021, successfully executing code inside the internal networks of Apple, Microsoft, Tesla, and dozens of other companies using nothing but public PyPI and npm packages named after internal dependencies. The proof-of-concept became a real attack in December 2022, when a malicious package called "torchtriton" appeared on PyPI with the exact name of a nightly-build dependency used internally by the PyTorch team. Because PyPI was configured with higher install priority than the private index in some pip configurations, machines that ran pip install torchtriton — including inside Meta's own infrastructure — pulled the public, poisoned version instead. The package exfiltrated system information, environment variables, and SSH keys to a remote server. PyTorch's maintainers had to publish a dummy "torchtriton" package on PyPI just to close the naming gap. This pattern is especially dangerous because it doesn't require a developer to make a mistake — it exploits the resolution logic of the build tool itself.

What happens when attackers hijack legitimate maintainer accounts?

Account hijacking works by taking over a trusted maintainer's PyPI credentials so malicious code can be pushed under a package's existing, trusted reputation. The clearest example is the "ctx" incident from May 2022: a maintainer had listed a contact email tied to a domain they no longer owned. A researcher (later joined by an actual attacker exploiting the same weakness) bought the expired domain, used it to reset the PyPI account password, and pushed a malicious 0.2.6 version of "ctx" — a package with roughly 20,000 weekly downloads at the time — that read AWS credentials and environment variables and sent them to a remote endpoint disguised as a Heroku app. The same expired-domain technique was used against the PHP package "phpass" in the same week, showing the attacker was working a list, not a single target. Because the package name, download history, and prior versions all looked legitimate, most static typosquat detection would have missed this entirely — the malicious code arrived through a channel developers had already learned to trust.

How are crypto wallet stealers hiding inside PyPI packages?

Crypto-stealing PyPI packages work by shipping fully functional utility code for months to build download counts and trust, then quietly adding theft logic in a routine-looking update. In November 2024, researchers at ReversingLabs identified "aiocpa," a package advertised as a client for the Crypto Pay API that had accumulated legitimate usage before a later version added code that exfiltrated private keys and seed phrases from any wallet the host application touched. Because the earlier versions were clean, the package had already passed casual review and built a plausible commit history before the backdoor shipped. This mirrors a broader wave: Socket's and Phylum's threat research teams have separately tracked clusters of "web3," "solana," and wallet-adjacent typosquats on PyPI that scrape .env files, browser-stored keys, and clipboard contents. The common thread is patience — these campaigns treat the package registry as a long con, not a smash-and-grab, which makes one-time code scans far less reliable than continuous monitoring of every new release.

Why did PyPI have to freeze new project registration in 2024?

PyPI froze new project and user account creation for about 10 hours in March 2024 because an automated campaign was uploading malicious packages faster than the volunteer moderation team could remove them. The flood used disposable, auto-generated package names and accounts, a technique researchers describe as "malware spam" — the goal isn't precision targeting, it's saturation, so that even a small conversion rate across thousands of uploads yields a meaningful number of infections. It was the first time in PyPI's history that the index had to pause public registration entirely to regain control, and it underscored a structural problem the registry has acknowledged: package intake at PyPI's scale (over 600,000 projects and growing) cannot rely on manual review to catch malicious uploads before install-time. It also validated what firms like Socket.dev have argued for years — that registry-level moderation alone isn't sufficient, and organizations need their own detection layer sitting between "published on PyPI" and "installed in our environment."

How Safeguard Helps

The patterns above share one uncomfortable trait: each of them looks legitimate at the exact moment a developer or CI pipeline installs the package. A typosquat has a working README. A dependency-confusion package has the exact name your build expects. A hijacked account has years of clean release history. A slow-burn crypto stealer has months of unremarkable versions before the payload lands. Catching these requires more than a one-time vulnerability scan against a CVE database — it requires behavioral and provenance analysis at the moment code changes hands.

Safeguard continuously analyzes new and updated packages across PyPI (and npm, crates.io, and other ecosystems) for the actual behaviors that show up in these campaigns: unexpected network calls to unfamiliar endpoints, environment variable and credential access patterns inconsistent with a package's stated purpose, obfuscated or dynamically executed code, and version-over-version diffs that flag a sudden jump in permissions or capabilities — the exact signal that would have caught "aiocpa" the moment its update shipped. Safeguard also tracks maintainer and account metadata, including ownership changes and contact-detail modifications, to surface hijacking risk the way the "ctx" and "phpass" incidents demanded, and it flags dependency confusion exposure by comparing your internal package namespace against public registries before a build ever resolves the wrong source.

Where competitors like Socket.dev focus primarily on install-time supply chain signals, Safeguard extends that coverage into your existing SDLC and compliance workflows — tying package risk findings directly to SOC 2 and audit evidence, and giving security teams a single view across open-source dependencies, CI/CD pipelines, and production runtime. The goal isn't to add another alert queue; it's to make sure that when a "torchtriton," a "ctx," or the next as-yet-unnamed campaign shows up on PyPI, it gets flagged before pip install ever runs in your environment — not after a postmortem.

If you manage dependencies at any scale, treat every new PyPI release the way these five patterns suggest you should: as untrusted until its behavior says otherwise. Reach out to see how Safeguard fits into your existing pipeline.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.