Skip to main content
Vulnerability Database/CVE-2026-96804

CVE-2026-96804: MLflow Statsmodel RCE Vulnerability

CVE-2026-96804 is a remote code execution vulnerability in MLflow statsmodel flavor versions 2.1.0 to 3.14.0 caused by missing pickle deserialization controls. This article covers technical details, affected versions, impact analysis, and mitigation strategies.

Published:

CVE-2026-96804 Overview

CVE-2026-96804 is an insecure deserialization vulnerability in the MLflow statsmodel model flavor. The flaw affects versions 2.1.0 through 3.14.0. The _load_model() function omits the MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False security control entirely, leaving pickle-based model loading unrestricted. A remote attacker with low privileges can execute arbitrary code by supplying a crafted MLmodel artifact. The vulnerability maps to CWE-502: Deserialization of Untrusted Data.

Critical Impact

Loading a malicious statsmodel artifact triggers arbitrary code execution in the MLflow process, compromising confidentiality, integrity, and availability of the model registry host.

Affected Products

  • MLflow statsmodel flavor, version 2.1.0
  • MLflow statsmodel flavor, versions 2.1.0 through 3.14.0
  • MLflow deployments that load third-party or user-supplied statsmodel artifacts

Discovery Timeline

  • 2026-09-23 - CVE-2026-96804 published to NVD
  • 2026-09-24 - Last updated in NVD database

Technical Details for CVE-2026-96804

Vulnerability Analysis

MLflow provides model flavors that wrap serialization and loading logic for different machine-learning frameworks. The statsmodel flavor persists models using Python pickle by default. MLflow introduced the MLFLOW_ALLOW_PICKLE_DESERIALIZATION environment flag so operators can block untrusted pickle loading across flavors.

In versions 2.1.0 to 3.14.0, the statsmodel flavor's _load_model() function does not consult this flag. The gate is missing from the code path, so pickle deserialization runs unconditionally. Setting MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False provides no protection for statsmodel artifacts.

An attacker who can register, upload, or substitute an MLmodel artifact can embed a malicious pickle payload. When a downstream user or automated pipeline calls mlflow.statsmodels.load_model(), Python executes attacker-controlled code inside the loading process. Refer to the CERT Vulnerability Advisory #369093 for further technical details.

Root Cause

The root cause is a missing security control in the _load_model() implementation of the statsmodel flavor. The function invokes pickle deserialization without checking the MLFLOW_ALLOW_PICKLE_DESERIALIZATION environment variable that other flavors honor. This is a classic instance of [CWE-502], where untrusted serialized data drives object reconstruction and callable execution.

Attack Vector

The attack vector is network-based and requires low privileges. An attacker needs the ability to place or reference a crafted MLmodel artifact reachable by the MLflow server or client. Typical scenarios include:

  • A contributor with model registry write access uploading a poisoned artifact.
  • A shared artifact store (for example, S3, Azure Blob, or a shared filesystem) where an attacker can write or replace files.
  • A downstream consumer loading a model pulled from an untrusted registry or URI.

Exploitation succeeds the moment a victim process calls the statsmodel load routine on the malicious artifact. The malicious payload runs with the privileges of the MLflow user, providing a foothold for lateral movement into training pipelines, secrets, and cloud credentials.

Detection Methods for CVE-2026-96804

Indicators of Compromise

  • Unexpected MLmodel or model.pkl files in artifact stores that were not produced by known training jobs.
  • Child processes spawned by MLflow workers that execute shells, curl, wget, or Python one-liners immediately after a load_model call.
  • Outbound network connections from MLflow tracking or serving hosts to unfamiliar domains shortly after model loads.
  • New credentials, SSH keys, or cron entries created on MLflow hosts following artifact ingestion.

Detection Strategies

  • Instrument MLflow servers to log every call to mlflow.statsmodels.load_model() with the source URI and calling user.
  • Alert on python or mlflow processes spawning interactive shells, package installers, or reverse-shell tooling.
  • Baseline network egress from MLflow infrastructure and flag deviations, especially connections to raw IPs or paste sites.

Monitoring Recommendations

  • Enable audit logging on artifact stores to record who wrote or modified MLmodel files.
  • Forward MLflow application logs and host process telemetry to a centralized analytics platform for correlation.
  • Monitor registry activity for artifact overwrites, version reassignments, or tag changes performed by low-privilege accounts.

How to Mitigate CVE-2026-96804

Immediate Actions Required

  • Inventory all MLflow deployments and confirm whether the statsmodel flavor is in use.
  • Restrict write access to model registries and artifact stores to trusted service accounts only.
  • Quarantine and re-review any statsmodel artifacts sourced from external contributors or public registries.
  • Isolate MLflow tracking and serving hosts on network segments with strict egress controls.

Patch Information

Upgrade MLflow to a version later than 3.14.0 that restores enforcement of MLFLOW_ALLOW_PICKLE_DESERIALIZATION in the statsmodel _load_model() path. Consult the CERT Vulnerability Advisory #369093 and the MLflow project release notes for the fixed version and upgrade guidance.

Workarounds

  • Avoid loading statsmodel artifacts from untrusted sources until the upgrade is applied.
  • Run MLflow workers under least-privilege service accounts with no access to production secrets.
  • Wrap load_model calls in a sandboxed process or container with restricted network and filesystem access.
  • Validate artifact provenance using signed manifests or hash allowlists before loading.
bash
# Configuration example: least-privilege service isolation for MLflow workers
# Restrict outbound network and filesystem scope for the mlflow user
sudo useradd --system --home /var/lib/mlflow --shell /usr/sbin/nologin mlflow
sudo chown -R mlflow:mlflow /var/lib/mlflow

# Deny egress except to the artifact store and tracking DB
sudo iptables -A OUTPUT -m owner --uid-owner mlflow -d <artifact-store-cidr> -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner mlflow -d <tracking-db-cidr> -j ACCEPT
sudo iptables -A OUTPUT -m owner --uid-owner mlflow -j REJECT

# Enforce the pickle deserialization flag at the process level (defense in depth)
export MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.