Skip to content

Response, New York. Noah Park: Check Point Patches Actively Exploited Management Server Path Traversal. Detection, Dallas. Ava Okello: Report Finds Nearly Half of Deployed Detections Need Attention Before SOCs Can Trust Them.

SOCtember

Always First. Fast SOC News.

Pluto Security illustration for its Load/Mine report: a cartoon monkey in a space suit tending a bank of mining machines.
Image: Pluto Security (fair use). Header art from Pluto's Load/Mine report, published Oct. 29, 2026.

Threat Intel

Pluto Security Says a Hugging Face Cryptomining Campaign Hid in 31 Fake Qwen2 Repositories That Run Code the Moment a Model Loads, and Came Back Within Days of a Takedown

The payloads ride on the trust_remote_code option rather than poisoned weights, scanned clean, and target self-hosted GPU inference servers such as Xinference and GPUStack. The top second-wave model passed 28,000 downloads, and Pluto says killing the miner leaves the backdoors in place.

Priya Shah, Threat IntelSingapore6 min read

SINGAPORE - A cryptomining and backdoor campaign that hid in Hugging Face repositories posing as small Qwen2 test models came back within days of being taken down, and its most popular second-wave model was downloaded 28,412 times before access to it was cut off, according to a report published on Thursday by the AI security company Pluto Security.

Pluto said it tracked 31 malicious repositories across seven Hugging Face accounts, published in two waves since September. The 19 second-wave repositories had been downloaded more than 29,000 times and were still live eight days after Pluto reported them, and with linked models the total passes 32,000. The company was careful about what that number means: it "measures downloads, not confirmed infections or unique victims."

The payloads were written for GPU hosts running self-hosted inference, especially Xinference and GPUStack, along with rented GPU machines, shared research notebooks and CI jobs that pull small test models without anyone reading the code.

The code runs before the model does

Pluto Security diagram of the attack chain, from enabling custom model code to a watchdog, a disguised miner and reports back to the operator.
Image: Pluto Security (fair use).The three-phase chain Pluto documented, from foothold to miner to status reporting.

The campaign used no poisoned weights and no pickle exploit. It relied on a documented Hugging Face option, trust_remote_code, that lets a repository ship its own Python implementation of a model. When a user enables it, the Transformers library imports that Python with the caller's privileges before any weights load, and any code placed next to the class definitions runs on the spot. In the flagship model, the weights file held no tensors and was 42 bytes long; the payload sat in a file called modeling_evil2.py.

That code first plants a foothold. A watchdog runs as a separate process, hooks in /root/.bashrc, /root/.profile and the user's .bashrc relaunch it, and it restarts a missing miner every 120 seconds. Three builds also open a reverse shell that reconnects after every disconnect. The downloader disables the host's configured proxies, so on a network that allows direct outbound traffic the fetch skips proxy inspection and logging.

The miner itself is a 40.6 MB binary packed with UPX, with the packer's markers altered so the standard unpacking tool fails while the embedded loader still runs. On first launch, the payload copies it into an in-memory file and executes it from there, so no executable path exists on disk for a file scanner, and the process list shows what looks like a kernel worker, [kworker/u20:1]. Pluto noted the tell: unlike a real kernel thread, the process carries userspace arguments, including the mining login. A fallback copy does stay on disk for relaunches. Status reports are written into the local Xinference model registry disguised as model names followed by base32-encoded text, and once its own miner is running the payload kills rival miners.

Clean scans, live wallets

Hugging Face runs every file under 2 GB through the ClamAV antivirus scanner at each commit, and partner scanners from Protect AI and JFrog inspect weight formats. None of that reads what a Python file does. The second-wave flagship "scanned clean while it collected 28,412 downloads," Pluto wrote, and JFrog reported the payload file was "not a machine-learning model." None of the 12 first-wave repositories was flagged.

The money was real. The first-wave payout wallet had received about 2,276 PRL across 716 transactions and was still active on public pool dashboards on Oct. 21, long after its repositories were removed. While Pluto watched, nine workers joined within 90 seconds of each other, with names that read like a shared notebook cluster, including an A100 GPU partition. They stopped about six minutes later, which Pluto said fits an administrator killing the jobs.

Takedown, then a second wave

Pluto Security diagram showing how a scanner hit on a test account and leftover backup files led to the campaign's production accounts.
Image: Pluto Security (fair use).How Pluto linked a throwaway test account to the rest of the campaign.

Pluto found the campaign through a throwaway account with six repositories created within 2.5 hours on Oct. 12. The attacker had copied production code into it and left behind two backup files whose older download URLs pointed to the main accounts. The first wave grew from a 37-line SSH backdoor to a 305-line fileless miner in about three weeks, with code comments in Simplified Chinese, and recorded more than 700 downloads before Hugging Face and China's ModelScope removed it.

A second wave of 19 repositories followed within days, with reverse shells in place of the planted SSH key. A container escape script that mounts host disks and gives the attacker root on the underlying server appeared 8.5 hours after Pluto's disclosure email, naming GPUStack as a second target. One later dropper served its second stage only to allow-listed IP addresses, so an analyst fetching the same URL could miss it.

Pluto Security chart of downloads by repository and account across both waves.
Image: Pluto Security (fair use).One repository accounts for 97.7 percent of second-wave downloads.

The flagship's count climbed from 7,354 at the time of Pluto's report to 18,012 on Oct. 25, 25,854 on Oct. 27 and 28,412 on Oct. 28. Hugging Face has since disabled access to it, BleepingComputer reported, but a near-identical copy uploaded on Oct. 25 by a newer account was still live at the time of that report. Pluto assessed the operator as financially motivated and Chinese-speaking, citing the comments, command-and-control servers on Alibaba Cloud and activity clustered between 18:38 and 21:19 UTC, late at night in China.

What responders should check

Pluto said anyone who loaded a listed model with custom code enabled should treat the machine as compromised even if loading failed or GPU use looks normal. It recommends isolating the host and capturing process details, connections, logs, model cache files, startup changes and registry entries before deleting anything; checking shell startup files, cron jobs, SSH authorized keys and model registrations; and rotating any tokens, cloud credentials, passwords and SSH keys the process could reach, from a clean machine. "Killing the miner or deleting the model does not remove persistence," the report said. Its quick checks include searching authorized_keys files for the key comment qx-5090-op and looking for connections to 212.32.253[.]3 on ports 443, 9443 and 8898.

For the longer term, the advice is to restrict the Xinference API, review and pin custom model code before loading it and run untrusted code with limited privileges, because "a clean scan alone is not a reason to trust it." As Pluto put it: "Until detection catches up, treat model code like any other software dependency: review it, pin it and isolate its runtime."

Sources:


Priya Shah covers threat intelligence, intrusion analysis, and adversary tradecraft for SOCtember from Singapore.

Related stories

Threat Intel desk