torch.package (PyTorch Package MFV) β€” picklescan/modelscan bypass PoC

Proof-of-concept model files for a huntr Model File Vulnerability (MFV) report against the PyTorch Package (.pt) format (torch.package).

Files

  • malicious_interned.pt β€” the actual vulnerability PoC. Runs os.system("touch /tmp/torch_package_interned_pwned") on load via torch.package.PackageImporter(...).load_pickle(...). Both picklescan (1.0.4) and modelscan (0.8.8, made by Protect AI, huntr's parent org) report this file as clean ("Infected files: 0" / "No issues found"). modelscan --show-skipped explicitly lists the payload file (archive/evilmodule.py) as skipped: "Model Scan did not scan file".
  • naive_detected_by_scanners.pt β€” control/comparison file. Same RCE effect, but the pickle directly references subprocess.Popen. Both scanners correctly flag this one as dangerous. Included to isolate exactly which part of the technique causes the bypass (embedding the payload in the package's own interned Python source module instead of referencing a known-dangerous stdlib global from the pickle opcodes).

Why the scanners miss it

torch.package archives are zip files that can bundle "interned" .py source modules alongside the pickle data. When such a module is imported (which routinely happens as part of unpickling a package object), torch/package/package_importer.py's PackageImporter._make_module() runs exec(code, ns) on that source directly. The pickle opcode stream itself never references anything scanners treat as dangerous (os.system, subprocess.Popen, eval, etc.) β€” it just references a custom, package-local class. Opcode-level scanners (picklescan, modelscan) have no model of this second execution path, so they see nothing to flag.

Reproduce

pip install torch picklescan modelscan
python3 -c "
import torch.package
picklescan_result = __import__('subprocess').run(['picklescan', '-p', 'malicious_interned.pt'])
"
picklescan -p malicious_interned.pt      # Infected files: 0
modelscan -p malicious_interned.pt        # No issues found! πŸŽ‰

python3 -c "
import torch.package
importer = torch.package.PackageImporter('malicious_interned.pt')
importer.load_pickle('archive', 'data.pkl')
"
ls -la /tmp/torch_package_interned_pwned  # created by the RCE

Full report: huntr.com MFV submission (PyTorch Package format).

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