Safeguard
Open Source Security

PyPI malware campaigns targeting machine learning and dat...

PyPI malware ML packages have hit PyTorch and Ultralytics YOLO via dependency confusion and CI/CD compromise. What happened, and how to defend your ML supply chain.

Vikram Iyer
Security Researcher
9 min read

Since late 2022, the Python Package Index has become a repeat target for attackers who understand exactly where the machine learning supply chain is weakest: the dependency tree. Security teams now track a recognizable pattern of PyPI malware ML packages campaigns — incidents that don't share a single CVE identifier but share the same playbook, from a dependency-confusion attack that hit PyTorch's nightly build pipeline to a cryptomining payload smuggled into the widely used Ultralytics YOLO package. Because data science workflows routinely run with elevated cloud credentials, GPU access, and CI/CD tokens, a single poisoned pip install can hand an attacker far more than a compromised laptop — it can hand over training infrastructure, cloud API keys, and model registries. This post walks through the best-documented incidents, what's actually confirmed about severity and exploitation, and what engineering teams should do in response.

What "PyPI Malware ML Packages" Actually Means

Unlike a traditional CVE that describes one flaw in one piece of software, the PyPI malware ML packages problem is a cluster of related techniques aimed at the same target population: developers pulling numpy, pandas, PyTorch, TensorFlow, scikit-learn, and their dozens of companion packages into training and inference environments. Researchers and package registries have documented three recurring attack shapes:

  • Typosquatting — publishing packages with names deliberately close to popular ML libraries (an extra character, a swapped hyphen, a common misspelling) so that a rushed pip install grabs the malicious copy instead.
  • Dependency confusion — exploiting the fact that public package indexes are often checked before or alongside private/internal ones, so an attacker who learns the name of an organization's internal package can publish a same-named malicious package publicly and have it installed instead.
  • Build and CI/CD pipeline compromise — tampering with the automated release process of a legitimate, high-trust package so that a malicious payload ships inside an otherwise authentic release.

Each of these has been used against ML-adjacent packages specifically, which is why this has become its own tracked category rather than a single incident. It's also why any malicious pypi package campaign targeting this ecosystem tends to have outsized blast radius — data science dependency trees are deep, frequently updated, and often installed by CI runners or notebooks with broad permissions.

Affected Packages and Versions

Two incidents anchor most of the public reporting on this problem, and both are well documented by the maintainers involved.

torchtriton (PyTorch nightly dependency, December 2022). PyTorch's nightly Linux builds installed via pip depended on an internal package named torchtriton, published only to PyTorch's own package index. Attackers registered a package with the identical name on the public PyPI. Because pip's index resolution did not strictly prioritize the private index over the public one, users who installed PyTorch nightly builds between December 25 and December 30, 2022 could receive the attacker's torchtriton instead of the legitimate one. The malicious package harvested system information — hostname, username, current working directory, environment variables, and DNS server configuration — along with the contents of ~/.gitconfig and up to the first 1,000 files in the user's home directory, including SSH keys, and exfiltrated them via DNS queries before removing itself. PyTorch's response team disclosed the incident publicly, advised affected users to check for and remove the malicious torchtriton package, rotate any potentially exposed credentials, and claimed placeholder packages on PyPI to close the naming gap.

Ultralytics YOLO (PyPI package ultralytics, December 2024). Ultralytics' YOLO object-detection library — one of the most widely used computer vision packages in the Python ecosystem — shipped versions 8.3.41 and 8.3.42 to PyPI containing an injected cryptomining payload (XMRig). The compromise did not originate from a stolen maintainer credential in the classic sense; it stemmed from a poisoned GitHub Actions build/cache step in the release pipeline that allowed an attacker to inject code into the package build before it was published. The malicious versions were pulled once discovered, and a clean release followed. Ultralytics and outside researchers documented that the attacker made at least one further attempt to slip a malicious build back into the pipeline shortly after the initial fix, underscoring how CI/CD compromise can persist even after a first remediation attempt.

Beyond these two headline cases, JFrog, Checkmarx, Phylum, Socket, and ReversingLabs have each published research over the past several years cataloguing ongoing typosquats of numpy, pandas, matplotlib, scikit-learn, tensorflow, and torch, along with infostealer payloads (including variants tracked as W4SP Stealer) distributed through look-alike packages and, separately, a phishing campaign against PyPI maintainers themselves (tracked as JuiceLedger) that led to compromised legitimate accounts publishing malicious updates. These campaigns collectively illustrate a sustained pypi ML dependency risk rather than a one-off event.

CVSS, EPSS, and KEV Context

This is a case where the standard vulnerability-scoring toolkit only partially applies, and it's worth being precise about why. CVSS scores a flaw in code logic; EPSS estimates the probability that a known vulnerability will be exploited; and CISA's KEV catalog tracks vulnerabilities under active exploitation. Malicious packages published directly to PyPI are not, technically, vulnerabilities in existing software — they're intentionally malicious code distributed through a trusted channel. As a result, most PyPI malware incidents, including torchtriton and the Ultralytics compromise, do not carry a traditional NVD CVSS score, and none of the incidents referenced here appear in the KEV catalog, which is scoped to exploited vulnerabilities rather than malicious package publications.

Where GitHub Security Advisories or package-registry advisories exist for these incidents, they are consistently rated at the top of the qualitative severity scale — full remote code execution on install, credential and SSH key theft, or unauthorized compute hijacking are each independently critical-impact outcomes. The practical takeaway for defenders: don't wait for a CVSS number to treat a malicious-package alert as urgent. If a dependency-scanning tool flags a package as known-malicious, the correct response time is "now," not "after triage against a severity score," because the entire point of these packages is to execute attacker code the moment they're installed.

Timeline of Notable Incidents

  • December 25–30, 2022 — Malicious torchtriton package uploaded to public PyPI exploits dependency confusion against PyTorch nightly builds; PyTorch discloses the incident and reserves placeholder package names.
  • Throughout 2022–2023 — The JuiceLedger threat actor runs a phishing campaign against PyPI maintainers, leading to compromised legitimate accounts publishing trojanized updates; parallel campaigns distribute the W4SP Stealer through typosquatted packages.
  • 2023–2024 — Repeated waves of typosquatted packages targeting numpy, pandas, and other data science staples are identified and removed by PyPI moderators, as documented in ongoing research from Checkmarx, Phylum, and Socket.
  • December 4–5, 2024 — Ultralytics YOLO versions 8.3.41 and 8.3.42 are published to PyPI containing an XMRig cryptominer injected via a compromised GitHub Actions build step; the packages are pulled and a clean release follows.
  • Shortly after, December 2024 — A follow-on attempt to reintroduce malicious code into the Ultralytics release pipeline is identified and blocked, prompting broader hardening of the project's CI/CD process.
  • 2025 — Security researchers continue to report new typosquats and dependency-confusion attempts against ML and AI tooling package names, reinforcing that this is an active, ongoing category rather than a closed chapter.

Remediation and Hardening Steps

Because this is a pattern rather than a single patchable flaw, remediation is about process and tooling, not a single version bump:

  1. Pin exact versions with hashes. Use pip install --require-hashes with a fully pinned requirements.txt, or a lockfile-based tool (Poetry, PDM, uv) so a newly published malicious version can't silently slip into a build.
  2. Fix index resolution order to prevent dependency confusion. If you maintain internal packages, explicitly configure --index-url for your private index and avoid relying on --extra-index-url fallback behavior that lets pip choose between a public and private package with the same name. Reserve your internal package names on public PyPI as placeholders.
  3. Vet new and unfamiliar packages before adopting them. Check maintainer history, repository links, release cadence, and download counts. A python data science supply chain attack often hides behind a plausible-looking name with a short history and few real users.
  4. Isolate credentials from install-time execution. Don't run pip install in environments that also hold long-lived cloud credentials, SSH keys, or CI secrets. Use ephemeral, least-privilege build environments so a malicious install script has nothing valuable to steal.
  5. Harden CI/CD build pipelines. Pin GitHub Actions to commit SHAs rather than mutable tags, restrict and audit cache scopes, and require multi-party review for changes to release workflows — the Ultralytics compromise happened at exactly this layer.
  6. Generate and monitor SBOMs continuously. A software bill of materials that's checked once at release time misses packages that turn malicious after the fact; continuous monitoring against updated threat-intel feeds is necessary to catch newly disclosed malicious packages in dependencies already deployed.
  7. Monitor runtime egress for anomalies. DNS-based exfiltration (as seen in torchtriton) and cryptomining beaconing (as seen in the Ultralytics compromise) both produce detectable network signatures if you're watching for them.

How Safeguard Helps

This is precisely the class of risk Safeguard is built to catch before it reaches production. Safeguard continuously monitors your dependency graph — including transitive ML and data science packages — against real-time feeds of known-malicious and typosquatted packages, so a compromised release like the Ultralytics incident or a dependency-confusion attempt like torchtriton gets flagged the moment it appears in a manifest or lockfile, not after it's already running in a training job. Safeguard's policy engine can gate CI/CD pipelines on package provenance and hash verification, blocking unpinned or newly published versions of high-risk packages from being pulled automatically. And because Safeguard maintains a living SBOM across your services rather than a point-in-time snapshot, it can retroactively surface every environment that installed an affected version once a new malicious-package disclosure lands — turning what used to be a frantic, manual audit into an automated query. For security and platform teams responsible for ML infrastructure, that combination of proactive blocking and retroactive visibility is what closes the gap between "a researcher published an advisory" and "we know exactly where we're exposed."

Never miss an update

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