MLflow pickle safety bypass in dspy, statsmodels flavors
MLflow's dspy and statsmodels model flavors can bypass the pickle-deserialization safety control, enabling remote code execution if an attacker controls the model source.
CERT/CC published VU#369093 describing a vulnerability in MLflow, an open-source ML lifecycle management platform, affecting the dspy and statsmodels model 'flavors'. MLflow previously introduced the MLFLOW_ALLOW_PICKLE_DESERIALIZATION environment variable as a safety control to let users block pickle deserialization when loading models. However, the dspy flavor only enforces this control when the specified model path ends in '.pkl' — an attacker or malicious model author can bypass the control simply by naming a pickle file with a different extension, causing MLflow to route to unprotected deserialization code. The statsmodels flavor is worse: it never checks the safety control at all, meaning pickle deserialization always occurs regardless of user configuration.
Successful exploitation allows arbitrary remote code execution via a malicious pickle payload embedded in a model, triggered when a victim loads the model through mlflow.pyfunc.load_model(). The precondition for exploitation is that an attacker has write access to a location from which a victim obtains MLflow models (e.g., a shared model registry, artifact store, or supply-chain path), making this a supply-chain-style risk within ML pipelines rather than a directly remotely exploitable network flaw. The issue was confirmed against MLflow 3.12.0.
MLflow's maintainers could not be reached to coordinate disclosure. The statsmodels flavor was silently patched in MLflow >= 3.15.0, and defenders should upgrade immediately. No fix currently exists for the dspy flavor issue; until one is released, organizations wishing to enforce pickle deserialization blocking should avoid loading models via the dspy flavor. There is no indication of in-the-wild exploitation; this is a vulnerability disclosure requiring proactive patching and configuration review of MLflow deployments, especially those with externally writable or shared model artifact stores.
Detection guidance
MLflow Model Loading with Pickle Deserialization
Detects Python interpreter executing mlflow.pyfunc.load_model() or statsmodels flavor deserialization, indicating potential malicious pickle payload execution. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: MLflow Model Loading with Pickle Deserialization
description: Detects Python processes executing MLflow model loading functions (pyfunc.load_model)
that may trigger unsafe pickle deserialization in dspy or statsmodels flavors. Triggers
when MLFLOW_ALLOW_PICKLE_DESERIALIZATION is not enforced or bypassed.
tags:
- attack.execution
- attack.t1059.001
- attack.t1195
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith:
- \python.exe
- \python3.exe
CommandLine|contains:
- mlflow.pyfunc.load_model
- statsmodels
filter_safe_mlflow:
CommandLine|contains: MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false
condition: selection and not filter_safe_mlflow
falsepositives:
- Legitimate ML pipeline orchestration tools loading models with pickle safety intentionally
enabled
- MLflow model serving infrastructure in development/testing environments
level: medium
id: 659b4cec-731b-5673-b3ff-43b706c63e80
status: experimental
author: Vorant
Python Pickle Deserialization from Non-Standard Model Files
Detects Python pickle.load() or pickle.loads() called on files with non-.pkl extensions in MLflow model directories, suggesting dspy flavor bypass. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: Python Pickle Deserialization from Non-Standard Model Files
description: Detects Python processes deserializing pickle data from files not ending
in .pkl (e.g., .bin, .dat, .model) within MLflow artifact/model directories. This
pattern indicates potential bypass of MLFLOW_ALLOW_PICKLE_DESERIALIZATION controls
in the dspy flavor.
tags:
- attack.execution
- attack.t1059.001
- attack.t1195
logsource:
category: process_creation
product: windows
detection:
selection:
Image|endswith:
- \python.exe
- \python3.exe
CommandLine|contains:
- pickle.load
- pickle.loads
- cloudpickle.load
model_dir:
CommandLine|contains:
- mlruns
- model_registry
- artifacts
non_pkl_extension:
CommandLine|re: \.(bin|dat|joblib|model|yaml|json|pkl2|pkls?\D|weights)\b
filter_legit_ml_tools:
CommandLine|contains:
- joblib.load
- torch.load
- tensorflow.saved_model
condition: (selection and model_dir and non_pkl_extension) and not filter_legit_ml_tools
falsepositives:
- ML frameworks (scikit-learn, PyTorch) loading serialized objects with non-.pkl naming
conventions in test/dev environments
- Legitimate model conversion utilities processing artifacts
level: medium
id: 8cd6f66e-a20d-5668-bb63-265fd0c6b239
status: experimental
author: Vorant
MLflow Process Environment Variable Absence - Pickle Safety Disabled
Detects MLflow model loading without MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false set, enabling statsmodels/dspy pickle bypass. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: MLflow Process Environment Variable Absence - Pickle Safety Disabled
description: Detects Python/MLflow processes loading models where MLFLOW_ALLOW_PICKLE_DESERIALIZATION
environment variable is not explicitly set to false, leaving statsmodels and dspy
flavors vulnerable to malicious pickle payloads.
tags:
- attack.execution
- attack.t1059.001
- attack.t1195
logsource:
category: process_creation
product: windows
detection:
selection_mlflow:
Image|endswith:
- \python.exe
- \python3.exe
CommandLine|contains: mlflow
selection_load:
CommandLine|contains:
- pyfunc.load_model
- load_model
filter_safe_config:
CommandLine|contains: MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false
filter_safe_env:
ParentCommandLine|contains: MLFLOW_ALLOW_PICKLE_DESERIALIZATION=false
condition: (selection_mlflow and selection_load) and not (filter_safe_config or
filter_safe_env)
falsepositives:
- MLflow CLI commands that do not load models (e.g., logging, model registration)
- Development environments where pickle safety is intentionally disabled for debugging
level: low
id: 71529091-02cd-534c-97d4-faa7b9dc7779
status: experimental
author: Vorant
Behavioural rules are generated from public reporting — validate in your environment before deploying.
Source reporting: https://kb.cert.org/vuls/id/369093
This is the public brief
Subscribers see the full picture: extracted IOCs, ready-to-deploy detections (Sigma, Splunk, KQL, Elastic, YARA, Suricata), the entity graph, TAXII 2.1 feed and real-time alerts matched to your sectors.
Start free