ModelScan Joblib NumPy Padding Bypass PoC
This repository contains benign proof-of-concept artifacts for a ModelScan scanner bypass affecting Joblib files.
Summary
ModelScan 0.8.8 detects a benign builtins.eval reduce target as CRITICAL when
it is stored directly in an uncompressed .joblib file.
The candidate file places the same benign payload after Joblib-serialized NumPy
array data. The Joblib NumPy alignment padding byte is shaped as 0x2e, which
is also pickle STOP, while extra padding preserves joblib.load()
alignment.
joblib.load() reaches the benign marker in the candidate, but ModelScan
reports total_issues: 0 and no scanner errors.
Files
control_direct.joblib- direct benign
builtins.evalmarker - expected ModelScan result: one CRITICAL issue
- direct benign
candidate_numpy_array_then_payload_patched.joblib- NumPy array followed by the same benign marker
- expected ModelScan result:
total_issues: 0,errors: []
joblib_numpy_padding_probe.py- reproduces the artifacts and prints loader/scanner results
Reproduction
python joblib_numpy_padding_probe.py
By default, the helper writes generated samples under
corpus/joblib_numpy_padding_probe/. Pre-generated copies are also included in
this repository root.
Expected key results:
- control:
joblib_load.status: okjoblib_load.marker_found: true- ModelScan
total_issues: 1 - ModelScan
errors: []
- candidate:
joblib_load.status: okjoblib_load.marker_found: true- ModelScan
total_issues: 0 - ModelScan
errors: []
Environment Used For Verification
- Python: 3.12.8
modelscan: 0.8.8joblib: 1.5.3numpy: 2.4.4
Safety Note
The PoC is intentionally benign. It returns only the static string
BENIGN_JOBLIB_MARKER.
It does not execute shell commands, read local files or credentials, perform network access, persist files, or attempt stealth.
This PoC demonstrates a scanner bypass / unsafe-global detection failure in ModelScan's Joblib handling. It does not claim a new Joblib RCE.