The Ultralytics PyPI Supply Chain Attack

Updated 5 Oct 2026 · Incident date 4 Dec 2024 · PyPI

Packageultralytics 8.3.40 -> 8.3.41, 8.3.42 (and again 8.3.45, 8.3.46)
Fileultralytics/models/yolo/model.py

The PyPI package ultralytics versions 8.3.41, 8.3.42, 8.3.45 and 8.3.46 installed a cryptocurrency miner. Version 8.3.40 was the last clean release before the attack in December 2024.

The first two versions came from a poisoned GitHub Actions workflow. The last two came from a stolen PyPI API token.

What happened

On 4 December 2024 an attacker abused the Ultralytics GitHub Actions publishing workflow. Socket reports that researcher Adnan Khan found the payload was delivered by GitHub Actions cache poisoning, using template injection in custom actions. HiddenLayer adds that the attack used branch names that carried malicious commands.

Socket gives this timeline in UTC:

Socket says the last two versions used an API token from the maintainer's account. Ultralytics had not deleted the old tokens when it registered a Trusted Publisher.

HiddenLayer describes the code changes. In 8.3.41 and 8.3.42, the files models/yolo/model.py and utils/downloads.py changed. The code detected the operating system and architecture, downloaded an XMRig miner and ran it through a new safe_run() function to mine Monero. Version 8.3.45 added code in __init__.py that sent environment variables and directory listings to a webhook service. Version 8.3.46 targeted Linux and downloaded XMRig 6.22.2 with wget.

Affected versions

Four releases of ultralytics on PyPI are affected.

Version 8.3.40 was clean. Version 8.3.43 and 8.3.44 are not named in the sources I fetched. Socket and HiddenLayer both say the code on GitHub did not match what PyPI served.

Indicators of compromise

HiddenLayer lists these indicators.

HiddenLayer reports that the webhooks received requests from Docker containers, Google Colab, GitHub Actions and AWS SageMaker.

How to check

Check the installed version.

pip show ultralytics

Version 8.3.41, 8.3.42, 8.3.45 or 8.3.46 means you were affected. Then look for the miner binary and process.

ls -l /tmp/ultralytics_runner; pgrep -fl ultralytics_runner

Search your lockfiles and image build logs for the bad versions.

grep -rnE "ultralytics(==|=| )8\.3\.(41|42|45|46)" . --include=requirements*.txt --include=*.lock --include=*.toml

What to do now

  1. Uninstall the affected version and install a clean release.
  2. Stop the ultralytics_runner process and delete /tmp/ultralytics_runner.
  3. Run a full antivirus scan.
  4. Rotate any token or key that was in the environment of the machine, especially for 8.3.45 and 8.3.46, which sent environment variables out.
  5. Check cloud bills for unexpected compute use.
  6. If you publish packages, remove old API tokens when you move to Trusted Publishing, and keep publishing in a dedicated workflow with scoped permissions.

Vigilance compares the version you trust with a new one and reports the file that gained a new capability. Here model.py gained download-and-run behavior. See all attacks.

What Vigilance showed

Vigilance compares the version you trust with the new one and names the file that gained a new capability. The block below is rebuilt from the public reports in the words Vigilance prints. It is not a captured scan, because the malicious release is not redistributed.

vigi diff --old ultralytics-8.3.40 --new ultralytics-8.3.41
files scanned: 45 (1 Added)

HEADS UP  1 file can now do things the old version could not. The rest changed and gained nothing.

NEW FILE   ultralytics/models/yolo/model.py
           It downloads from the internet and runs other programs.

Frequently asked questions

Which ultralytics versions were compromised?

Versions 8.3.41, 8.3.42, 8.3.45 and 8.3.46 on PyPI installed a cryptocurrency miner. Version 8.3.40 was clean.

How was Ultralytics compromised?

The first two versions came from GitHub Actions cache poisoning in the publishing workflow. The last two came from a stolen PyPI API token.

Sources

  1. hiddenlayer.com/research/ultralytics-python-package-compromise-deploys-cryptominer
  2. socket.dev/blog/ultralytics-pypi-package-compromised-through-github-actions-cache-poisoning

More supply chain attacks

All 111 attacks in the library · What is a supply chain attack? · How to prevent supply chain attacks

Check the next update before you install it

Vigilance compares the version you trust with the new one. It names the one file that can now do something it could not do before.

Start Free