Downloads · 30 days
0
liamramsey/modelscan-legacy-pt-bypass-poc
modelscan-legacy-pt-bypass-poc is a machine learning model from liamramsey. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as mit.
Authorized security research. Benign marker payload only (touch /tmp/POCPWNEDtorch). For huntr.com Model File Format disclosure.
Downloads · 30 days
0
Access
Public
Updated Jun 3, 2026
Repo size
3 KB
Likes
0
Public
Click a slice to open those files.
.md2.8 KB · 45%
From the Hugging Face model README
.pt, payload behind the magic-number pickleAuthorized security research. Benign marker payload only (touch /tmp/POC_PWNED_torch). For huntr.com Model File Format disclosure.
ModelScan's PyTorch scanner (scan_pytorch → scan_pickle_bytes(..., multiple_pickles=False)) reads only the first pickle stream of a .pt file. PyTorch's legacy serialization format (torch.save(obj, f, _use_new_zipfile_serialization=False)) is a sequence of separate concatenated pickle streams: pickle(MAGIC_NUMBER), pickle(PROTOCOL), pickle(sys_info), then pickle(payload), then storages.
Because multiple_pickles=False stops after the first stream (the magic number), the malicious __reduce__ payload in a later stream is never parsed. ModelScan reports the file clean — total_issues: 0, errors: [], scanned: 1 (it believes it fully scanned a clean file). torch.load(f, weights_only=False) still executes the payload.
This is distinct from the publicly documented PyTorch legacy attacks, which are tar-based (3 files in a tar) or rely on crashing the scanner via ZipFile/STACK_GLOBAL exceptions. This variant is a flat, non-tar stream that scans clean with zero errors.
evil_legacy.pt — the bypass: flat legacy .pt, payload in a later pickle stream. ModelScan: clean.evil.pt — control: identical payload in the modern zip format. ModelScan: flagged CRITICAL os.system.build.py — builds both.pip install modelscan torch
python build.py
modelscan -p evil_legacy.pt # => "No issues found!", Total Issues 0 (BYPASS)
modelscan -p evil.pt # => Total Issues 1, CRITICAL os.system (control, caught)
python -c "import torch; torch.load('evil_legacy.pt', weights_only=False)" # marker /tmp/POC_PWNED_torch created
Same file, only the scan flag differs:
_list_globals(..., multiple_pickles=False) → globals found: set() (what ModelScan does)_list_globals(..., multiple_pickles=True) → globals found: {('os','system')}Confirms the bypass is the container/scan-flag, not the payload.
Requires torch.load(weights_only=False). torch ≥2.6 defaults weights_only=True, but weights_only=False is exactly the scenario ModelScan exists to defend, and remains common (e.g. NeMo forces it False; much existing code passes it). Tested: modelscan 0.8.6, torch 2.8.0, Python 3.9.
In scan_pytorch, scan with multiple_pickles=True for legacy-format .pt files (iterate every concatenated pickle stream), not just the first.