VORANT. Threat Intelligence Sign in Get the full feed

MLflow pickle safety bypass in dspy, statsmodels flavors

routine vulnerability technology

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

ATT&CK T1059.001

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

ATT&CK T1059.001

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

ATT&CK T1059.001

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