Articles / The Ultralytics YOLO Compromise: A Poisoned Build Pipeline on PyPI
Incident File · 2024

The Ultralytics YOLO Compromise: A Poisoned Build Pipeline on PyPI

In December 2024, users who ran pip install ultralytics — pulling one of the most popular computer-vision libraries in the Python ecosystem — could have received a cryptominer instead of a model. Two malicious versions reached the Python Package Index, and the way they got there is the part worth studying: the attacker never needed the maintainer's publishing credentials.

The compromise was analysed by several firms, including ReversingLabs, Socket, and others. Versions 8.3.41 and 8.3.42 of the ultralytics package were published containing code that downloaded and executed the XMRig cryptominer on affected systems. The library's popularity — it is a default choice for object detection — meant the blast radius was large and immediate.

Poisoning the pipeline, not the password

The interesting mechanism was GitHub Actions cache poisoning. The project's automated workflow built and published releases to PyPI using trusted publishing — a design meant to remove long-lived credentials from the process. Researchers described how a crafted pull request could poison the build cache that the release workflow relied on, so malicious code was folded into the artifacts the trusted pipeline then published. The attacker subverted the build, and the legitimate automation signed and shipped the result.

Attacker poisonsGitHub Actions cacheCI builds viatrusted publishingMalicious versionon PyPIpip install pullsa cryptominerPoisoned build, nota stolen token
Poison the build, not the password.
Why it matters: Trusted publishing removes the stolen-token risk but not the poisoned-build risk. If an attacker can influence what your CI builds, your most trusted release channel will distribute their payload for them.
The user's experience gave nothing awaypip install ultralytics # resolves to 8.3.41
# post-install: fetches and runs XMRig cryptominer

The response

The malicious releases were pulled quickly, and the maintainers moved to harden the workflow. The clean-up was itself instructive: an initial follow-up release still carried the malicious code before a genuinely clean version resolved it, and further tainted versions briefly appeared afterward before being removed. Incident response on a compromised pipeline is hard precisely because the thing you use to ship the fix is the thing that was subverted.

For the AI ecosystem specifically, this matters because model and vision libraries sit deep in data pipelines, often on machines with GPUs, cloud credentials, and network reach. A cryptominer was the visible payload; the same access could have done far more.

The choice of a cryptominer is almost a courtesy, in that it made the compromise noticeable — miners are loud, spiking CPU and GPU usage in ways monitoring tends to catch. A quieter attacker, using the same access, could have exfiltrated the cloud credentials and datasets that vision pipelines routinely sit beside, or established persistence, with far less chance of discovery. There is a specific reason this class of attack targets AI libraries: machine-learning packages are frequently installed on infrastructure that is valuable and permissive at once — GPU instances, CI runners with deploy credentials, notebooks wired into data lakes. Combine that with a culture of pulling the newest version to chase model improvements, and you have fertile ground for supply-chain compromise. Pinning dependencies feels like friction against that culture, which is exactly why it has to be deliberately imposed rather than left to habit.

What defenders should take away

  • Pin and verify dependencies. Pin exact versions and hashes so a freshly published malicious release cannot be pulled automatically, and review changes before bumping.
  • Harden CI as production. Treat build caches, workflow triggers, and pull-request permissions as security-critical; untrusted contributions must not influence release builds.
  • Watch for post-install behaviour. Network calls and process spawns during installation of an ML library are a red flag worth alerting on.
  • Know your dependency tree. You cannot assess exposure to a compromised package if you do not know it is in your environment.

The Ultralytics incident showed that modern software supply-chain attacks aim upstream of the maintainer, at the automation that everyone trusts. Defending against it starts with a real inventory of what your models and pipelines depend on — because you cannot defend what you have not discovered.

Keep reading
nullifAI: Malicious Models That Slipped Past Hugging Face's Scanner