nullifAI: Broken Pickles That Slipped Past Model Scanning
On this page
Attackers don't just hide from scanners — they craft payloads specifically to break them.
| When | February 2025 |
|---|---|
| Target | Hugging Face model hub (Picklescan) |
| Researcher | ReversingLabs |
| Technique | Broken/non-standard pickle to evade scanning, opcodes run early |
| Impact | Reverse shell on load while bypassing detection |
- 1An attacker stores a malicious model as a deliberately broken, 7z-compressed pickle
- 2The scanner can't parse it and fails to flag it; torch.load can't open the 7z archive
- 3But when the pickle is deserialised, the malicious opcodes run first — a reverse shell fires before the stream 'breaks'
What happened
In February 2025, ReversingLabs found malicious Hugging Face models that carried a reverse-shell payload but were stored as PyTorch pickles compressed with 7z instead of the default ZIP. As a result torch.load couldn't open them and Hugging Face's Picklescan failed to flag them — yet the malicious opcodes, placed early in the stream, still executed during deserialisation before the “broken” file errored out. They named the evasion “nullifAI.” ReversingLabs judged the two models more likely a proof of concept than an active campaign.
How the attack worked
The attacker exploited a gap between the scanner's parser and the deserialiser: the file looked un-scannable/invalid to the tool, but the runtime still ran the payload's opcodes before hitting the error.
Root cause
Relying on a single scanner as the control, against an unsafe format an attacker can deliberately malform to slip past it.
What a control would have caught
Defence in depth — sandboxed loading and preferring safetensors — contains the payload even when a scanner is evaded, which signature-only detection cannot.
How to prevent it
- Don't trust a scanner as your only gate; assume evasion.
- Prefer safetensors; sandbox any pickle-based load.
- Update detectors for malformed inputs (Picklescan was patched here).
Feel it yourselfThe replay lab loads a backdoored model file — the malicious-model class this evasion belongs to.
FAQ
How did it evade detection?
The models were stored as pickles compressed with 7z instead of the default ZIP, so torch.load couldn't open them and Picklescan failed to flag them — but the malicious opcodes, placed early in the stream, still ran during deserialisation before the file errored out.
What's the broader lesson?
Scanner-based defences are necessary but not sufficient: attackers specifically craft payloads to defeat known scanners. Defence in depth (sandboxed loading, safetensors) matters.
Was it fixed?
Hugging Face removed the models within about a day of notification, and Picklescan was updated to detect threats in corrupted pickle files.
Sources
- Malicious ML models discovered on Hugging Face platform — ReversingLabs
- Malicious ML Models on Hugging Face Leverage Broken Pickle Format to Evade Detection — The Hacker News
- Malicious ML models found on Hugging Face Hub — Help Net Security