MLflow's Scorer Allow-List Trusted a Name Prefix, and an Uploaded File Could Borrow It

CVE-2026-116692, published October 27 with a CVSS 3.1 score of 9.8, lets a caller turn MLflow's own artifact storage into a code-execution path on servers running 3.12.0 through 3.16.x. The fix shipped in MLflow 3.17.0 on October 7, but the CVE is what will put unpatched tracking servers on scanners' lists.

A brass key cut to fit a row of identical mailbox locks, one unmarked box at the end of the row standing slightly open
A brass key cut to fit a row of identical mailbox locks, one unmarked box at the end of the row standing slightly open

An allow-list is only as strict as the comparison behind it. In MLflow’s case, the check that decided which Python modules the server would load as evaluation “scorers” asked whether a module’s name began with a trusted prefix, not whether it was the trusted module. That gap is now CVE-2026-116692. It entered the National Vulnerability Database at 21:18 UTC on October 27, 2026 (2:48 AM IST on October 28), and GitHub’s advisory database listed it as GHSA-26p8-2jq9-3vq9 minutes later. It carries a CVSS 3.1 base score of 9.8, with no privileges or user interaction required, and GitHub classifies it under CWE-94 (code injection) and CWE-470 (unsafe reflection).

MLflow describes itself as “an open source AI engineering platform for agents, large language models, and machine learning models.” The affected code belongs to its GenAI evaluation layer, so the exposure is concentrated in teams that use MLflow tracking servers to score LLM and agent output.

Versions and the fix

The advisory covers MLflow 3.12.0rc0 up to, but not including, 3.17.0. The vulnerable behavior arrived with a pull request titled “Enable third-party scorer registration in OSS MLflow” (#22634). According to the advisory it is absent from 3.11.1 and first appears in 3.12.0, which reached PyPI on May 5, 2026.

The fix is in MLflow 3.17.0, released October 7. Its changelog lists the change as “Match third-party scorer modules exactly instead of by package prefix (GHSA-26p8-2jq9-3vq9)” in pull request #25906. The newest release on PyPI is 3.17.2. The repository advisory was published by MLflow maintainer tanghaoji, and GitHub credits the user mskca as the reporter. The report’s own test notes are dated July 12, 2026, when no fixed release existed yet.

How a name check let an uploaded file run as code

MLflow 3.12 let the open-source server deserialize scorers from four third-party evaluation integrations. The allowed module roots are mlflow.genai.scorers.ragas, mlflow.genai.scorers.deepeval, mlflow.genai.scorers.trulens and mlflow.genai.scorers.phoenix. The deserializer accepted any module path equal to one of those roots or starting with one of them followed by a dot. It then imported the module, fetched a class named in the request and instantiated it with request-supplied arguments.

On its own, a prefix check only matters if an attacker can place a file under one of those packages. The advisory shows that MLflow’s ordinary tracking API can do exactly that. The chain has five steps:

  1. Create an experiment whose local artifact location points into a writable allowed scorer package.
  2. Create a run, which makes MLflow allocate <artifact_location>/<run_id>/artifacts/.
  3. Upload a Python module into that run’s artifact directory.
  4. Submit a serialized third-party scorer whose module path resolves to the uploaded file.
  5. Call /ajax-api/3.0/mlflow/scorer/invoke to trigger the import and class construction.

Nothing gets overwritten. The uploaded file simply becomes a new, importable module such as mlflow.genai.scorers.trulens.<run_id>.artifacts.<name>, and it passes the prefix test. The handler also deserializes and constructs the scorer before it looks at the trace IDs in the request, so the attacker’s constructor runs even though the request then fails with an HTTP 500.

The researcher reproduced this on the official ghcr.io/mlflow/mlflow:v3.14.0 image with authentication switched off, which is the default. In that image the server ran as root and could write to its own installed Python package tree.

When authentication is on

Turning on MLflow’s basic authentication raises the bar but doesn’t remove the bug. The advisory says the scorer-invoke endpoint is mapped to a check that returns true without verifying permission on the specific experiment or scorer. An authenticated user who can create experiments and runs and upload artifacts can still walk the same chain. The advisory also names the conditions that break it: a read-only container filesystem, or scorer package directories owned by a different user that the server process can’t write to.

The same 3.17.0 release tightened the scorer path in other ways. It rejects “egress-steering” arguments in third-party scorer payloads (GHSA-2wqp-q3c6-ccj5), authorizes scorer/invoke and binds traces to the caller’s experiment (GHSA-6c27-cp6h-c66m), and confines custom scorer code execution to the job executor.

What operators should check

  • Upgrade any MLflow server running 3.12.x through 3.16.x to 3.17.0 or later.
  • Don’t expose an unauthenticated tracking server beyond a trusted network. The advisory’s impact statement covers “any network caller who can reach the tracking server.”
  • Run the server as a non-root user with a read-only package tree, so that artifact uploads can’t land inside importable code.
  • On servers that ran affected versions, look for unexpected experiments whose artifact locations point into site-packages, and rotate any credentials the server process could read.

GitHub’s database entry is new, and no public reports of exploitation have appeared. Because the CVE arrived three weeks after the patch, the main risk is to pinned or forgotten tracking servers that never picked up 3.17.0.

Topics
  • #MLflow
  • #CVE-2026-116692
  • #LLM Evaluation
  • #Remote Code Execution
  • #Python Security
Raj M

Author

Raj M

Contributor

AI Systems Architect is a seasoned technology leader with over 15 years of experience in the IT industry working with Fortune 500 companies. With a solid foundation in multi-agent systems, open-source LLM infrastructure, and enterprise deployment, he excels at building scalable production-grade AI platforms.