crafted.joblib / README.md
qingyi26's picture
Upload folder using huggingface_hub
6e918ff verified
metadata
library_name: joblib
tags:
  - joblib
  - security
  - poc

ModelScan 0.8.8 blind spot PoC for current-format .joblib

A crafted current-format .joblib artifact preserves an authentic outer wrapper prefix but appends a nested payload beyond the wrapper boundary. Public ModelScan 0.8.8 reports 0 issues on the artifact, while joblib.load() reconstructs a hidden LogisticRegression estimator whose inference output changes under a trigger input.

The file crafted.joblib looks like a tiny dtype=object NumpyArrayWrapper at the outer prefix level, but joblib.load() reconstructs a hidden LogisticRegression estimator with trigger-based output manipulation.

Reproduction

pip install joblib==1.5.3 scikit-learn numpy
python repro.py

Expected output:

<class 'sklearn.linear_model._logistic.LogisticRegression'>
0
1

Meaning:

  • ordinary input [[1.5]] predicts class 0
  • trigger input [[100.0]] predicts class 1

Public scanner result:

  • Protect AI public ModelScan 0.8.8: 0 issues, 0 errors

PoC construction

build_artifact.py generates crafted.joblib by:

  1. creating a benign file with joblib.dump(np.array([1], dtype=object), ...)
  2. reusing the first 220 bytes of that benign file unchanged
  3. appending a nested pickle payload containing a backdoored LogisticRegression

So the malicious artifact keeps an authentic current-format Joblib wrapper prefix while the active model payload starts after the wrapper boundary.

Note:

  • this repository demonstrates a clean result in Protect AI public ModelScan 0.8.8
  • it does not claim direct testing of Huntr's private production scanner