Wysoka

MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False safety control bypassed by mlflow.statsmodels flavor — RCE via crafted model artifact

  • Ujawniono: 01.09.2026
  • Aktualizacja: 11.10.2026 15:17

Summary

MLflow introduced MLFLOW_ALLOW_PICKLE_DESERIALIZATION as a security control to prevent unsafe pickle.load execution during model loading, in response to CVE-2024-37052 through CVE-2024-37060. When set to False, operators expect all pickle deserialization to be blocked. The most recent related fix (#21188) patched a bypass in the pyfunc flavor.

However, the mlflow.statsmodels flavor completely omits this guard. An attacker who places a crafted MLmodel artifact into any accessible artifact store can trigger arbitrary code execution on any process that calls mlflow.pyfunc.load_model() against the malicious model — even when MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False.

This is a security control bypass. The operator believes pickle RCE is mitigated; the statsmodels flavor silently ignores the control.


Root Cause

mlflow.pyfunc.load_model() dispatches to flavor _load_pyfunc implementations via:

# mlflow/pyfunc/__init__.py L1170-1172
model_impl = importlib.import_module(conf[MAIN])._load_pyfunc(data_path)

The guarded pattern (from mlflow/sklearn/__init__.py L526-533, the reference implementation) is:

if (
    not MLFLOW_ALLOW_PICKLE_DESERIALIZATION.get()
    and not is_in_databricks_runtime()
    and not is_in_databricks_model_serving_environment()
):
    raise MlflowException("Deserializing model using pickle is disallowed...")

mlflow/statsmodels/__init__.py has no such check:

python
# L307-320 — no guard anywhere in this file
def _load_model(path):
    import statsmodels.iolib.api as smio
    return smio.load_pickle(path)   # calls pickle.load() directly

def _load_pyfunc(path):
    return _StatsmodelsModelWrapper(_load_model(path))

statsmodels.iolib.api.load_pickle is a thin wrapper around pickle.load. Its own docstring warns: "Never unpickle data received from an untrusted or unauthenticated source."


Trigger

An attacker crafts an MLmodel YAML that specifies mlflow.statsmodels as the loader module:

flavors:
  python_function:
    loader_module: mlflow.statsmodels
    data: model.pkl
  statsmodels:
    data: model.pkl
    statsmodels_version: 0.14.0

With a malicious model.pkl placed alongside it in the artifact store, any call to:

os.environ["MLFLOW_ALLOW_PICKLE_DESERIALIZATION"] = "False"
mlflow.pyfunc.load_model("models:/MaliciousModel/1")

...deserializes the pickle file with no guard check, executing arbitrary code with the privileges of the calling process.

On default MLflow deployments (no --app-name basic-auth), authentication is disabled, so artifact upload requires no credentials.


Affected Code

  • mlflow/statsmodels/__init__.py L307-310: _load_model — calls smio.load_pickle without checking MLFLOW_ALLOW_PICKLE_DESERIALIZATION
  • mlflow/statsmodels/__init__.py L313-320: _load_pyfunc — dispatches to _load_model without checking the control

Permalink (commit 0b0c576c):


Recommended Fix

Add the missing guard to mlflow/statsmodels/__init__.py:

python
from mlflow.environment_variables import MLFLOW_ALLOW_PICKLE_DESERIALIZATION
from mlflow.utils.databricks_utils import (
    is_in_databricks_model_serving_environment,
    is_in_databricks_runtime,
)

def _load_model(path):
    if (
        not MLFLOW_ALLOW_PICKLE_DESERIALIZATION.get()
        and not is_in_databricks_runtime()
        and not is_in_databricks_model_serving_environment()
    ):
        raise MlflowException(
            "Deserializing model using pickle is disallowed, but this statsmodels "
            "model requires pickle deserialization. Set environment variable "
            "'MLFLOW_ALLOW_PICKLE_DESERIALIZATION' to 'true' to allow this."
        )
    import statsmodels.iolib.api as smio
    return smio.load_pickle(path)

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Python (PyPI) mlflow >= 2.1.0, < 3.15.0 3.15.0

Odnośniki

Ocena CVSS 8.8/10
Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Słabość (CWE)
CWE-502
Platforma
Python (PyPI)
Paczka
mlflow
Ujawniono
01.09.2026
Aktualizacja
11.10.2026 15:17

Źródła i licencje

OSV / GitHub Advisory Database - GHSA-gqvg-gmmx-x4hm - CC BY 4.0

Historia podatności: mlflow

Wszystkie opisane podatności tej paczki (Python (PyPI)), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (82) w archiwum
Wszystkich wpisów
82
Pierwsza → ostatnia
02.2022 09.2026
Bez poprawki
18
Wykorzystywana w atakach
1

Rozkład istotności

  • Krytyczna 20
  • Wysoka 48
  • Średnia 13
  • Niska 1

Ujawnienia w latach

  1. 2022: 1
  2. 2023: 22
  3. 2024: 24
  4. 2025: 8
  5. 2026: 27
Istotność:
  1. MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False safety control bypassed by mlflow.statsmodels flavor — RCE via crafted model artifact ten wpis
    Wysoka · 8.8 ghsa-gqvg-gmmx-x4hm >= 2.1.0, < 3.15.0 3.15.0
  2. Wysoka · 7.1 CVE-2026-71211 >= 3.13.0, <= 3.15.2 brak poprawki
  3. Wysoka · 8.1 CVE-2026-8147 >= 2.14.0rc0, < 3.13.0rc0 3.13.0rc0
  4. Wysoka · 7.0 CVE-2026-4137 >= 1.26.0, < 3.11.0 3.11.0
  5. Krytyczna · 10.0 CVE-2025-15379 < 3.8.1 3.8.1
  6. Krytyczna · 9.6 CVE-2025-15036 < 3.9.0rc0 3.9.0rc0
  7. Wysoka · 8.1 CVE-2025-15381 <= 3.8.1 brak poprawki
  8. Wysoka · 8.1 CVE-2025-15031 < 3.9.0rc0 3.9.0rc0
  9. Wysoka · 7.5 CVE-2025-14287 < 3.8.0rc0 3.8.0rc0
  10. Krytyczna · 9.8 CVE-2026-2635 < 3.8.0rc0 3.8.0rc0
  11. Wysoka · 7.0 CVE-2025-10279 < 3.4.0rc0 3.4.0rc0
  12. Wysoka · 8.1 CVE-2025-11200 < 2.22.0rc0 2.22.0rc0
  13. Wysoka · 8.1 CVE-2025-11201 < 2.22.4, >= 3.0.0rc0, < 3.0.0 2.22.4, 3.0.0
  14. Wysoka · 7.5 CVE-2024-8859 < 2.17.0rc0 2.17.0rc0
  15. Wysoka · 8.8 CVE-2024-37061 >= 1.11.0, <= 2.13.1 brak poprawki
  16. Wysoka · 8.8 CVE-2024-37057 >= 2.0.0rc0, <= 2.14.1 brak poprawki
  17. Wysoka · 8.8 CVE-2024-37058 >= 2.5.0, <= 2.14.1 brak poprawki
  18. Wysoka · 8.8 CVE-2024-37060 >= 1.27.0, <= 2.14.1 brak poprawki
  19. Wysoka · 8.8 CVE-2024-37059 >= 0.5.0, <= 3.4.0 brak poprawki
  20. Wysoka · 8.8 CVE-2024-37054 >= 0.9.0, <= 2.14.1 brak poprawki
  21. Wysoka · 8.8 CVE-2024-37052 >= 1.1.0, <= 2.14.1 brak poprawki
  22. Wysoka · 8.8 CVE-2024-37055 >= 1.24.0, <= 2.14.1 brak poprawki
  23. Wysoka · 8.8 CVE-2024-37056 >= 1.23.0, <= 2.14.1 brak poprawki
  24. Wysoka · 8.8 CVE-2024-37053 >= 1.1.0, <= 2.14.1 brak poprawki
Pokaż więcej (20) Widać 40 z 68

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.