/

CVE-2026-116692

Severity:

CRITICAL RISK

(9.8)

Arbitrary Code Execution (CWE-94) in MLflow Scorers

CVE-2026-116692

Awaiting Analysis

Vulnerability type

Category:

Code Injection

CWE:

CWE-94, CWE-470

Impact:

Remote Code Execution

Severity:

CRITICAL RISK

(9.8)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

Summary

MLflow's third-party scorer handling may import and instantiate a caller-selected Python class from a module located beneath a writable allowed package. This can enable arbitrary code execution in the MLflow server process when an attacker can submit scorer metadata and write artifacts to the relevant package path.

MLflow's third-party scorer handling may import and instantiate a caller-selected Python class from a module located beneath a writable allowed package. This can enable arbitrary code execution in the MLflow server process when an attacker can submit scorer metadata and write artifacts to the relevant package path.

Affected context

The issue occurs in MLflow deployments that expose scorer invocation and use third-party scorer deserialization. Risk is present when the server process can load Python modules from a writable package location and a caller can provide scorer module and class metadata. Authentication-disabled deployments may expose this capability without credentials, while basic-auth deployments require a principal with sufficient experiment, run, and artifact permissions.

The issue occurs in MLflow deployments that expose scorer invocation and use third-party scorer deserialization. Risk is present when the server process can load Python modules from a writable package location and a caller can provide scorer module and class metadata. Authentication-disabled deployments may expose this capability without credentials, while basic-auth deployments require a principal with sufficient experiment, run, and artifact permissions.

Exploit preconditions

  • Attack surface: MLflow scorer invocation and artifact endpoints
  • Required access: No credentials in authentication-disabled deployments; otherwise, an authenticated principal able to create experiments and runs and upload artifacts
  • Trigger point: Third-party scorer validation and construction during scorer invocation
  • Required filesystem condition: The allowed scorer package must be writable by the MLflow server process
  • Why exploitation is possible: Request-selected module descendants are accepted without requiring an exact approved module, allowing imported code to be loaded and a class to be instantiated before normal trace processing
  • Attack surface: MLflow scorer invocation and artifact endpoints
  • Required access: No credentials in authentication-disabled deployments; otherwise, an authenticated principal able to create experiments and runs and upload artifacts
  • Trigger point: Third-party scorer validation and construction during scorer invocation
  • Required filesystem condition: The allowed scorer package must be writable by the MLflow server process
  • Why exploitation is possible: Request-selected module descendants are accepted without requiring an exact approved module, allowing imported code to be loaded and a class to be instantiated before normal trace processing

Why this happens

The vulnerability results from insufficient allowlist enforcement during dynamic Python module loading. Instead of requiring an exact match against approved third-party scorer modules, the implementation accepts request-selected descendants beneath an allowed package and then imports and constructs the referenced class.

This behavior maps primarily to CWE-94: Improper Control of Generation of Code, because attacker-influenced input controls which executable Python component is loaded. It is also related to CWE-470: Use of Externally-Controlled Input to Select Classes or Code, as untrusted metadata influences class selection and instantiation.

The vulnerability results from insufficient allowlist enforcement during dynamic Python module loading. Instead of requiring an exact match against approved third-party scorer modules, the implementation accepts request-selected descendants beneath an allowed package and then imports and constructs the referenced class.

This behavior maps primarily to CWE-94: Improper Control of Generation of Code, because attacker-influenced input controls which executable Python component is loaded. It is also related to CWE-470: Use of Externally-Controlled Input to Select Classes or Code, as untrusted metadata influences class selection and instantiation.

Potential impact

  • The attacker may execute arbitrary code with the privileges of the MLflow server process.
  • The attacker could access or alter local files, credentials, models, and experiment data available to that process.
  • The compromise could enable lateral movement into connected infrastructure.
  • The attacker may tamper with artifacts, traces, runs, or other machine-learning workflow outputs.
  • The vulnerability could support data theft, persistence, or supply-chain manipulation.
  • The attacker may execute arbitrary code with the privileges of the MLflow server process.
  • The attacker could access or alter local files, credentials, models, and experiment data available to that process.
  • The compromise could enable lateral movement into connected infrastructure.
  • The attacker may tamper with artifacts, traces, runs, or other machine-learning workflow outputs.
  • The vulnerability could support data theft, persistence, or supply-chain manipulation.

General mitigation guidance

Mitigation generally focuses on eliminating attacker control over dynamically imported scorer code and reducing the trust placed in writable artifact locations.

Common defensive patterns include:

  • Require exact module and class identifiers from a narrowly defined, immutable registry rather than accepting arbitrary descendants of an allowed package.
  • Avoid importing or instantiating Python classes based directly on request-controlled metadata.
  • Treat uploaded artifacts and scorer definitions as untrusted data, and keep them separate from executable package paths.
  • Make approved scorer packages non-writable by the MLflow server process and use read-only deployment images where practical.
  • Run MLflow with a dedicated least-privilege identity, restricted filesystem access, and limited network permissions.
  • Require authentication and enforce authorization boundaries around experiment, run, artifact, and scorer operations.
  • Isolate scorer execution in a constrained worker or sandbox with minimal access to secrets and infrastructure.

Mitigation generally focuses on eliminating attacker control over dynamically imported scorer code and reducing the trust placed in writable artifact locations.

Common defensive patterns include:

  • Require exact module and class identifiers from a narrowly defined, immutable registry rather than accepting arbitrary descendants of an allowed package.
  • Avoid importing or instantiating Python classes based directly on request-controlled metadata.
  • Treat uploaded artifacts and scorer definitions as untrusted data, and keep them separate from executable package paths.
  • Make approved scorer packages non-writable by the MLflow server process and use read-only deployment images where practical.
  • Run MLflow with a dedicated least-privilege identity, restricted filesystem access, and limited network permissions.
  • Require authentication and enforce authorization boundaries around experiment, run, artifact, and scorer operations.
  • Isolate scorer execution in a constrained worker or sandbox with minimal access to secrets and infrastructure.

How teams detect issues like this

Detection approaches can include:

  • Static analysis rules for imports, reflection, class construction, and deserialization controlled by request or artifact metadata.
  • Code review checks for prefix-based allowlists that do not enforce exact module identity.
  • Monitoring for unexpected writes beneath Python package directories or other executable paths used by the MLflow server.
  • Application logging and alerting for unusual scorer module names, class selections, artifact uploads, or scorer invocation patterns.
  • Policy enforcement preventing server processes from writing to executable code locations.
  • Automated security review tools can help identify externally controlled class selection and dynamic import paths, but findings should be validated against deployment permissions and filesystem layout.

Detection approaches can include:

  • Static analysis rules for imports, reflection, class construction, and deserialization controlled by request or artifact metadata.
  • Code review checks for prefix-based allowlists that do not enforce exact module identity.
  • Monitoring for unexpected writes beneath Python package directories or other executable paths used by the MLflow server.
  • Application logging and alerting for unusual scorer module names, class selections, artifact uploads, or scorer invocation patterns.
  • Policy enforcement preventing server processes from writing to executable code locations.
  • Automated security review tools can help identify externally controlled class selection and dynamic import paths, but findings should be validated against deployment permissions and filesystem layout.

Sources

SourceLink
github.comgithub.com/mlflow/mlflow/commit/a732443e695c3c677680c54320efc394c81654ab
github.comgithub.com/mlflow/mlflow/pull/25906
github.comgithub.com/mlflow/mlflow/releases/tag/v3.17.0
github.comgithub.com/mlflow/mlflow/security/advisories/GHSA-26p8-2jq9-3vq9

Frequently asked

questions

It can be remotely exploitable when scorer invocation and artifact endpoints are reachable and the attacker satisfies the required artifact and scorer permissions. Authentication-disabled deployments have a broader exposure scope, while authenticated deployments depend on the privileges assigned to the caller.

In an authentication-disabled deployment, credentials may not be required. In a basic-auth deployment, the attacker generally needs a principal capable of creating an experiment and run and uploading artifacts, along with a writable allowed scorer package.

Require exact, server-controlled module and class mappings, prevent request data from selecting executable Python components, and ensure artifact storage cannot modify executable package locations.

Use strict allowlists, isolate untrusted scorer execution, apply least privilege, monitor writes to code paths, and enforce authorization for artifact and scorer operations.

It can be remotely exploitable when scorer invocation and artifact endpoints are reachable and the attacker satisfies the required artifact and scorer permissions. Authentication-disabled deployments have a broader exposure scope, while authenticated deployments depend on the privileges assigned to the caller.

In an authentication-disabled deployment, credentials may not be required. In a basic-auth deployment, the attacker generally needs a principal capable of creating an experiment and run and uploading artifacts, along with a writable allowed scorer package.

Require exact, server-controlled module and class mappings, prevent request data from selecting executable Python components, and ensure artifact storage cannot modify executable package locations.

Use strict allowlists, isolate untrusted scorer execution, apply least privilege, monitor writes to code paths, and enforce authorization for artifact and scorer operations.

Find out what's already
exploitable in your codebase.