| # Security-research PoC — model-scanner bypass (picklescan / ModelScan) |
|
|
| **This is a benign security-research proof-of-concept for a coordinated vulnerability disclosure to |
| [huntr](https://huntr.com)'s Model File Format program.** It is not malware. |
|
|
| `model.pt` is an 89-byte PyTorch/pickle file that demonstrates a **parser desync** between the static |
| model scanners (picklescan, ModelScan — both walk pickles with `pickletools.genops`, base-10 int parsing) |
| and the real C unpickler (`_pickle`, base-0 int parsing). The 6-byte `INT` opcode `I0x10\n` makes the |
| scanners' opcode walk abort **before** the payload, so both scanners report the file clean, while |
| `torch.load()` executes the payload. |
|
|
| **The payload is intentionally harmless:** it writes a marker file to the system temp directory |
| (`NOMOS_SCANNER_BYPASS`) to prove code execution. No data is exfiltrated, nothing is destroyed, there is |
| no network activity and no self-propagation. |
|
|
| ## Reproduce |
| ``` |
| pip install picklescan==1.0.5 modelscan==0.8.8 torch |
| picklescan -p model.pt # -> exit 0, PRISTINE (0 dangerous globals) |
| modelscan scan model.pt # -> "No issues found" |
| python -c "import torch; torch.load('model.pt', weights_only=False)" # -> marker written = code executed |
| ``` |
|
|
| ## Responsible-disclosure notes |
| - Reported to huntr's model-file program (their required submission mechanism is a public HuggingFace PoC repo). |
| - Suggested fix for the scanner maintainers: `genops`-based walkers must fail **closed** (UNSAFE) on any parse |
| abort, and align INT opcode parsing with the C unpickler (or reject non-decimal INT args). |
|
|
| Full write-up: see the disclosure package accompanying this PoC. |
|
|