nullifAI: Malicious Models That Slipped Past Hugging Face's Scanner
In February 2025, ReversingLabs researcher Karlo Zanki reported two malicious machine-learning models hosted on Hugging Face that used a novel evasion trick the firm nicknamed nullifAI. The models are a compact lesson in a truth the AI supply chain keeps relearning: a model file can be executable code, and "we scan for that" is only as good as the scanner.
The danger lives in Python's pickle serialization format, which many models use. Unpickling an object can execute arbitrary code embedded in the stream — which is why platforms that host models run scanners to flag dangerous pickle payloads. Hugging Face uses a tool called Picklescan for exactly this. The nullifAI models were built to defeat it.
How the evasion worked
ReversingLabs described two tricks working together. First, the models were compressed with 7z rather than the ZIP format PyTorch expects, so the standard torch.load() would not automatically load them — sidestepping the obvious path while still being usable by a targeted victim. Second, and more cleverly, the malicious pickle stream was deliberately corrupted: the dangerous opcode that spawned a reverse shell to a hardcoded address was placed early in the stream, before the point where the corruption caused parsing to fail. The payload executed first; the scanner, choking on the broken stream afterward, failed to flag it.
The response
Hugging Face removed the offending models within roughly a day of disclosure, and Picklescan was updated to detect threats hiding in broken pickle files. The system corrected itself quickly — but only because an outside researcher found the gap. The episode is a reminder that model hubs are software registries in disguise, and pulling an unknown model is closer to running an unknown binary than most data-science workflows acknowledge.
It also pairs naturally with the tenant-isolation research others have published: whether the risk is a malicious model escaping a shared platform or a malicious model landing on your own machine, the root cause is the same — treating model artifacts as inert data when they are, in fact, code.
The deeper worry the technique exposes is a mismatch in how the ecosystem treats models versus how it treats code. A developer who would never run a random executable downloaded from a stranger will happily torch.load() a model pulled from a public hub, because the mental model is "data, not program." Pickle-based formats quietly violate that assumption: loading the model runs code. Attackers understand this gap perfectly, which is why model hubs have become a supply-chain frontier — the malicious artifact arrives dressed as a helpful pre-trained model, and the victim's own workflow executes it. Scanner evasion adds a second layer: once a platform advertises that it scans uploads, attackers craft payloads to defeat the specific tool while users relax because "it was scanned." The healthy posture is to treat scanning as one probabilistic layer among several, never a guarantee.
What defenders should take away
- Prefer safe formats. Where possible, use
safetensorsor other non-executable serialization instead of pickle-based formats. - Do not equate "scanned" with "safe." Assume attackers craft payloads to evade your specific tools; sandbox model loading regardless of scan results.
- Vet model provenance. Source models from trusted publishers, verify integrity, and be wary of unofficial re-uploads.
- Inventory the models you run. Every third-party model in your pipeline is executable code you have chosen to trust; you cannot govern the ones you have not catalogued.
nullifAI shows attackers are already tailoring payloads to the exact security tools defenders rely on for AI artifacts. Staying ahead means knowing every model your teams have pulled and treating each as untrusted code until proven otherwise — because you cannot defend what you have not discovered.