cmpndry's picture
Upload 3 files
4cbb7df verified
|
Raw
History Blame Contribute Delete
2.19 kB
metadata
license: mit
tags:
  - security-poc
  - coordinated-disclosure

PoC: modelscan 0.8.8 multi-pickle legacy scan bypass (scanner evasion)

Coordinated-disclosure proof-of-concept submitted to huntr. The model file in this repository is a benign test artifact: its payload only runs touch MP_legacy_pwn (creates an empty marker file in the working directory). No network access, no destructive action. Do not load untrusted model files.

What this demonstrates

modelscan 0.8.8 reports evil_legacy.pt as clean ("No issues found! ๐ŸŽ‰", exit 0), yet torch.load("evil_legacy.pt", weights_only=False) executes the payload. The identical os.system operator in a single-stream pickle is flagged โ€” so this is a scan-coverage correctness defect, not a denylist gap.

This is a scanner-evasion finding (huntr "unique methods to bypass our automated scanners"), not a report of pickle deserialization itself. Root cause: scan_pytorch() (modelscan/tools/picklescanner.py) calls scan_pickle_bytes(..., multiple_pickles=False), so _list_globals() breaks after the first of the file's sequential pickle streams and never inspects the model object graph.

How the PoC model was created

A well-formed 5-stream PyTorch legacy file: magic number, protocol, sys_info, the os.system payload object, and an empty storage-keys list (so torch.load returns without error โ€” a valid file, not malformed). See poc.py.

Files

  • evil_legacy.pt โ€” the malicious-but-benign model file (modelscan-clean, executes on load).
  • poc.py โ€” self-contained: builds the file, scans it (clean), loads it (executes), and runs a single-stream control (flagged). One command.

Reproduce

pip install "modelscan==0.8.8" torch
modelscan -p evil_legacy.pt        # -> No issues found! ๐ŸŽ‰  (exit 0)
python -c "import torch; torch.load('evil_legacy.pt', weights_only=False)"   # -> creates MP_legacy_pwn
python poc.py                       # full differential, prints: RESULT: PASS

Affected / fix

modelscan 0.8.8 (latest at disclosure). Fix: pass multiple_pickles=True in the PyTorch legacy scan path (scan_pytorch), matching the non-legacy behaviour.