~100 Backdoored Models Found on Hugging Face
On this page
A model file is not inert data — with pickle, loading it can run code. About 100 on Hugging Face did.
| When | February 2024 |
|---|---|
| Target | Hugging Face model hub / model users |
| Researcher | JFrog Security Research |
| Technique | Malicious pickle __reduce__ → code execution on load |
| Impact | Silent backdoor / reverse shell on the victim's machine |
- 1An attacker uploads a model whose pickle payload runs on deserialisation
- 2A data scientist loads the model with a normal torch.load
- 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.