The most uncomfortable finding in Pluto Security‘s research is not only that malware reached a major AI model hub. It is that the hub’s scanning looked at the malware and found nothing wrong. None of the 12 first-wave repositories was flagged, and the second-wave flagship scanned clean while it collected 18,012 downloads.
What the Hub actually scans
Hugging Face does scan repository files, and documents it. Its malware scanning page states that every file smaller than 2 GB is run through the ClamAV antivirus scanner at each commit, which matches known malware signatures. Its pickle scanning page says the scanning “doesn’t cover pickle exploits,” so the Hub also extracts and displays the imports inside pickle files. Partner scanners cover the weight formats: Protect AI Guardian for pickle, Keras and other model exploits, and JFrog for malicious behavior in model files. The same pickle page says the scanning is “not 100% foolproof” and that checking whether something is safe is the user’s responsibility.
The surface no one inspects
A Python file in a repository is scanned, but by a signature matcher, not by anything that reads what the code does. This campaign sits in that gap. A plain Python file referenced by auto_map is neither a known malware signature nor a serialized model. In Pluto Security’s checks, modeling_evil2.py inside qwen2-tiny returned safe from every scanner that ran: antivirus clean, and JFrog reporting it was not a machine-learning model. The same held for the wave-one files. The flagship’s model.safetensors is a 42-byte file with no tensors.
A feature doing its job
The execution is a documented opt-in. Setting trust_remote_code=True tells the library to import the code an auto_map entry names, and the Transformers security policy advises developers to “always verify the content of the modeling files when using this argument.” Pluto Security says that works only if people actually read the code. In practice, model cards and tutorials copy trust_remote_code=True, and the flag meant as an informed opt-in becomes a checkbox.
Still live, five days on
The first wave was removed after Pluto Security reported it to Hugging Face and ModelScope. When the second wave was disclosed on October 20, the repositories stayed up. The flagship grew from 7,354 to 9,584 downloads within hours and stood at 18,012 on October 25, five days after disclosure. The binary it serves unpacks to peakminer, and one wallet from the first wave is still earning.
What would have caught it
Pluto Security’s own approach shows the alternative. Its scanner targets the files trust_remote_code actually downloads and runs: every .py file referenced by auto_map in a config.json, plus any Python file sitting beside model weights. A model definition should describe layers and a forward pass, so imports of subprocess, socket or ctypes, or calls to memfd_create, are red flags. Reviewing the .py files an auto_map points to, before the flag is set, would have caught every payload in this campaign. A static check at upload time for subprocess, socket, ctypes or raw-IP network calls in files referenced by auto_map would have caught them earlier still.
The rest of the campaign, in short
A financially motivated, Chinese-speaking operator or small group is assessed to have run the campaign since September 2026 across two waves and more than 40 code iterations, spanning 28 repositories across six Hugging Face accounts and a ModelScope mirror, 35 with linked models, and 21,614 downloads in all. The payloads evolved from an SSH backdoor to fileless mining with reverse shells, hiding the miner as a kernel thread and blending into Xinference directories, and the backdoors they plant outlast the miner.
The takeaway for the ecosystem
A clean scan alone is not a reason to trust a repository. Until detection catches up, Pluto Security says to treat model code like any other software dependency: review it, pin it and isolate its runtime.


















