| --- |
| license: mit |
| tags: |
| - security-research |
| - vulnerability-poc |
| --- |
| |
| # Security PoC (MLflow shap pickle safety bypass) |
|
|
| **This is a security proof-of-concept model, NOT a real ML model.** |
|
|
| This MLflow shap-flavor model demonstrates that `MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false` is silently bypassed by the shap flavor. When loaded via `mlflow.pyfunc.load_model()`, the explainer's pickle payload executes arbitrary code before the type check raises. |
|
|
| ## Vulnerability |
|
|
| MLflow documents `MLFLOW_ALLOW_PICKLE_DESERIALIZATION` as a global protection. When set to `false`, loading any pickle-based model should raise an error. The shap flavor loads explainers via `shap.Explainer.load()` which calls `pickle.load(in_file)` in `_instantiated_load()` -- neither mlflow's shap integration nor shap's own `Explainer.load` consult the toggle. |
|
|
| ## Reproduction |
|
|
| ```bash |
| pip install mlflow==3.14.0 shap |
| export MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false |
| python -c "import mlflow; mlflow.pyfunc.load_model('<this-repo-path>')" |
| # marker file written to /tmp/aisc0005_shap_mfv_pwned |
| ``` |
|
|
| ## Impact |
|
|
| A deployer who hardened via `=false` still gets arbitrary code execution when a shap-flavor model is loaded, including via the pyfunc scoring server. |
|
|
| ## Responsible disclosure |
|
|
| Submitted via huntr.com Model File Format program. |
|
|