genai
SECURITY LAB
IncidentsSupply chain

~100 Backdoored Models Found on Hugging Face

High severityFebruary 2024LLM04: Supply Chain
Status: Reported publicly; reinforced Hugging Face's pickle/malware scanning (Picklescan)
On this page

A model file is not inert data — with pickle, loading it can run code. About 100 on Hugging Face did.

WhenFebruary 2024
TargetHugging Face model hub / model users
ResearcherJFrog Security Research
TechniqueMalicious pickle __reduce__ → code execution on load
ImpactSilent backdoor / reverse shell on the victim's machine
Attack flow
  1. 1An attacker uploads a model whose pickle payload runs on deserialisation
  2. 2A data scientist loads the model with a normal torch.load
  3. 3The payload executes and opens a reverse shell on their machine

What happened

In early 2024, JFrog's scanning of Hugging Face identified roughly 100 malicious models that execute attacker code the moment the model is loaded. Most abused Python's pickle format (PyTorch's default serialisation), embedding a payload in the object's __reduce__ method; a highlighted case opened a reverse shell to a hardcoded address, with other repos pointing elsewhere.

How the attack worked

Pickle deserialisation can run arbitrary code. A poisoned model is a normal-looking file that runs its payload during torch.load — before you ever run inference.

Root cause

Treating third-party model files as inert data. In an unsafe serialisation format, loading a model is executing untrusted code.

What a control would have caught

Scanning models for dangerous pickle opcodes before load, and loading only in a sandbox, catches this class — as does preferring a non-executable format.

How to prevent it

  • Prefer safetensors over pickle-based formats.
  • Scan and sandbox model loads; treat model files as untrusted code.
  • Pin and verify model provenance/hashes.

Feel it yourselfThe replay lab loads a backdoored model that triggers attacker behaviour — the malicious-model supply-chain class.

FAQ

How does loading a model run code?

PyTorch's default serialisation uses Python pickle, which can execute arbitrary code on deserialisation via the object's __reduce__ method. A poisoned model runs its payload the instant you load it.

What did the payloads do?

A highlighted case opened a reverse shell to a hardcoded address, giving the attacker control of the victim's machine; other repos pointed at different addresses.

How do you defend against it?

Prefer safetensors over pickle, scan models before loading (e.g. Picklescan), and treat third-party model files as untrusted code, not inert data.

Replay this attack
Load a backdoored model that triggers attacker behaviour — the malicious-model supply-chain class.
Open the live lab
Runs as a live, sandboxed lab. Sign-in required — this replay is a Pro lab. Recreates the attack class, not this exact branded bot.