Security Digest · Oct 27, 2026 · Vulnerability · AI / LLM
MLflow CVE-2026-116692: Unauthenticated RCE via Scorers
MLflow 3.12.0-3.16.x servers without auth let anyone run code by uploading a fake scorer module. Fixed in 3.17.0; PoC public. Patch exposed servers this week.
Our verdict
Patch this week
No exploitation is reported, but the advisory spells out a five-step chain to code execution on default no-auth MLflow servers, so upgrade to 3.17.0 or later this week and today for any server reachable beyond your own team.
Who must act: Teams running an MLflow tracking server from 3.12.0rc0 up to 3.17.0, especially the official Docker image or any install where the server process can write to its own Python packages, and above all servers reachable without authentication.
Who can relax: Users of MLflow below 3.12.0 or at 3.17.0 and later, local-only servers on the default 127.0.0.1 binding, people who only use the MLflow client library, and servers whose package directories are read-only to the server process.
- Affected
- MLflow 3.12.0rc0 through 3.16.x (pip: mlflow >= 3.12.0rc0, < 3.17.0), including ghcr.io/mlflow/mlflow images in that range
- Fixed in
- MLflow 3.17.0 (released October 7, 2026; 3.17.2 is current)
- CVSS
- 9.8 (v3.1, CNA)
- EPSS
- 0.7% (percentile 53)
- CISA KEV
- Not listed
- Exploitation
- Public proof-of-concept
- Severity
- Critical
What to do
- Check every tracking server: pip show mlflow, or docker exec <container> pip show mlflow; anything from 3.12.0rc0 up to 3.17.0 is affected.
- Upgrade to 3.17.0 or later (pip install -U "mlflow>=3.17.0" or pull a 3.17.x image) and restart the server.
- Until upgraded, take the server off untrusted networks and put it behind authentication (MLflow basic auth, a VPN or an identity-aware proxy).
- Make the server's Python package tree read-only: run the container as a non-root user with a read-only root filesystem; the advisory says this blocks the chain.
- If an affected server was reachable without authentication, run the checks below and rotate every credential the server process could read (artifact store keys, database URIs, cloud roles, LLM API keys).
How to check if you are affected or compromised
- Search access logs for POST /ajax-api/3.0/mlflow/scorer/invoke, especially from clients you do not recognize.
- List experiments with search_experiments(view_type=ViewType.ALL) and flag any whose artifact_location points into site-packages or the mlflow/genai/scorers package.
- Look for run-artifact directories or unexpected .py files inside the installed mlflow package tree, for example under mlflow/genai/scorers/.
- Check the server host or container for processes, outbound connections or files the MLflow service does not normally create.
What happened#
On October 27, MLflow published GHSA-26p8-2jq9-3vq9, assigned CVE-2026-116692 and scored CVSS 3.1 9.8 by GitHub, the CNA. MLflow 3.12.0 added support for registering and deserializing "third-party scorers", the evaluation plugins built on TruLens, Ragas, DeepEval and Phoenix. When the server deserializes a scorer, it takes a Python module path and class name from the request. It checks only that the module path begins with one of the allowed package names, then imports the module and instantiates the class.
A prefix is not a trust boundary. According to the advisory, an HTTP caller can chain built-in MLflow endpoints:
- Create an experiment whose local artifact location points inside a writable allowed scorer package, such as
mlflow/genai/scorers/trulens. - Create a run, which makes MLflow allocate
<artifact_location>/<run_id>/artifacts/. - Upload a Python file as a run artifact.
- Submit a serialized scorer whose module path resolves to that file.
- Call
/ajax-api/3.0/mlflow/scorer/invoke, which imports the file and runs its code inside the server process.
The reporter reproduced this on the official ghcr.io/mlflow/mlflow:v3.14.0 image with default settings. That image runs as uid 0 and lets the process write to its own package tree, so the result is unauthenticated arbitrary Python execution as root inside the container. The advisory includes a harmless proof of concept.
The fix, PR #25906, replaces the prefix match with an exact allow-list of 14 modules. It also requires the resolved class to be a Scorer subclass and rejects dotted metric names. It shipped in MLflow 3.17.0, which PyPI shows was released on October 7, three weeks before the advisory. The same release fixed two related scorer issues, including missing authorization on scorer/invoke (GHSA-6c27-cp6h-c66m).
Who is affected#
MLflow tracking servers from 3.12.0rc0 up to, but not including, 3.17.0. All three of these conditions must hold:
- Reachable: the attacker can send HTTP requests to the server.
mlflow serverbinds to 127.0.0.1 by default, but shared team servers, Kubernetes deployments and Docker setups usually listen more widely. - Allowed by authentication: with authentication off, the default, no credentials are needed. With basic auth on, the attacker needs an account that can create experiments and runs and upload artifacts, which on many shared servers is every user.
- Writable packages: the server process can write beneath an allowed scorer package. The official image allows this. A read-only container filesystem, or a package directory owned by another user, blocks the chain.
Using MLflow only as a client library, logging to a hosted or patched server, is not affected.
Do you really need to act?#
If you run a shared MLflow server in the affected range, yes, this week. No exploitation has been reported and CISA has not listed the CVE. However, the advisory documents the chain step by step, every step uses a normal MLflow API, and the default configuration of the official image meets every precondition. MLflow servers also tend to hold valuable secrets: artifact store keys, database URIs, cloud roles and, increasingly, LLM provider API keys. Attackers have exploited MLflow before. An unauthenticated SSRF, CVE-2026-64849, was added to CISA's KEV catalog on August 19, 2026.
A server that only binds to localhost on a developer laptop is a low priority. Exposed servers without authentication are not, and they should be patched today.
What to do now#
- Check versions:
pip show mlflowon the server host, ordocker exec <container> pip show mlflow. - Upgrade:
pip install -U "mlflow>=3.17.0", or move to a 3.17.x image, then restart. 3.17.2 is the current release. - Until upgraded, remove the server from untrusted networks and require authentication in front of it, using MLflow basic auth, a VPN or an identity-aware proxy.
- Harden the deployment whatever version you run. Use a non-root user and a read-only root filesystem (
docker run --read-only --user 1000:1000 ...with a separate writable volume for artifacts), so that uploaded files can never land inside importable code. - If an affected server was reachable without authentication, run the checks below and rotate the credentials the server process could read.
How to tell if you were hit#
- Search access logs for
POST /ajax-api/3.0/mlflow/scorer/invokefrom unfamiliar clients, particularly right after experiment creation, run creation and artifact uploads from the same source. - List experiment artifact locations, including deleted experiments:
python -c "import mlflow; from mlflow.entities import ViewType; [print(e.experiment_id, e.artifact_location) for e in mlflow.search_experiments(view_type=ViewType.ALL)]"withMLFLOW_TRACKING_URIset. Any location insidesite-packagesis a red flag. - Look for uploaded files inside the installed package:
find "$(python -c 'import mlflow, os; print(os.path.dirname(mlflow.__file__))')/genai/scorers" -name artifacts -type d. - Review the container or host for unexpected processes, outbound connections and files.
Timeline#
- — MLflow 3.12.0 adds third-party scorer deserialization.
- — The fix (PR #25906) is merged.
- — MLflow 3.17.0 is released with the fix.
- — The advisory and CVE-2026-116692 are published.
Vulnerability records
- CVE-2026-116692 · MLflow is an open source AI engineering platform for agents, large language models, and machine learning models.
Sources
Original sources first: vendor and project advisories, CVE and government records, the discoverers’ write-ups. Every claim above links to one of these. See how the Security Desk works.
Original and primary sources
- MLflow — GHSA-26p8-2jq9-3vq9: Remote code execution via third-party scorer deserialization github.com
- CVE record — CVE-2026-116692 cve.org
- MLflow — PR #25906: Match third-party scorer modules exactly instead of by package prefix github.com
- MLflow — Release v3.17.0 github.com
- PyPI — mlflow release history pypi.org
- GitHub Advisory Database — GHSA-26p8-2jq9-3vq9 github.com
- Mend.io — WS-2026-0135: MLflow third-party scorer deserialization RCE mend.io