Ultralytics (PyPI): CI branch-name injection leads to cryptominer in releases 8.3.41, 8.3.42, 8.3.45 and 8.3.46 (no CVE)
Severity: high · Patch status: patched · Since 2024-12-04
Between 2024-12-04 and 2024-12-07 four releases of the ultralytics package on PyPI (8.3.41, 8.3.42, 8.3.45, 8.3.46) shipped code that downloaded and ran an XMRig cryptocurrency miner when a YOLO model was created; in 8.3.45 and 8.3.46 the downloader sat in init.py and ran on import. The attacker opened pull requests whose branch names carried shell commands into a pullrequesttarget workflow built on the ultralytics/actions action, getting code execution with repository secrets; researchers think a poisoned build cache then altered the release artifacts, which were published through the project's genuine Trusted Publisher workflow so the malicious code was in the wheels but not the public repo. The second wave was uploaded straight to PyPI with an API token that had not been revoked, with no attestations. PyPI removed all four versions (the last at about 10:09 UTC on 12-07) and says no PyPI flaw was used; Trusted Publishing provenance is what made the first wave auditable.
What to do
- Search environments, containers, lockfiles and CI caches for ultralytics 8.3.41, 8.3.42, 8.3.45 or 8.3.46; use 8.3.40 or a later release you have verified by hash
- On any host that ran them, look for the dropped miner binary and unexpected CPU use, rebuild images, and rotate secrets reachable from the host
- In your own repos, remove pull_request_target workflows that put branch names or PR titles into shell steps, drop pip/setup-python caching from release builds, and revoke leftover long-lived PyPI API tokens once Trusted Publishing is on
- Compare published wheels to the source repo and check PyPI provenance attestations for releases that lack them
Sources
All live incidents on Threat Watch