A Model Registry With an Outbound Dial: What CVE-2026-64849 Hands an Unauthenticated Caller
MLflow accumulates privilege quietly. Experiment tracking, artefact storage and the model registry sit behind one HTTP service, and that service is normally reachable from the same segment as the object store, the internal package index and whatever metadata endpoint the cloud provider exposes. So a webhook handler that fetches a caller-supplied URL without checking who is calling is not really a webhook problem. It is a question about everything the server can reach.
What the flaw actually is
CVE-2026-64849 covers a missing authentication check on the MLflow webhook endpoint. A request that should have required an authenticated session was accepted anonymously, and the URL carried in that request was then fetched by the MLflow server itself. The advisory is published as GHSA-7gwp-5pfp-969j and the vulnerable window closes at 3.15.0. NVD scores it 9.3, which is the right order of magnitude for an unauthenticated server-side request forgery on a platform holding model artefacts.
Two details in the fix are worth reading closely, because they explain why the obvious mitigation is insufficient. The first is redirects: the initial request can point at a hostname the operator considers safe, and the response can then redirect deeper. Any validation that inspects only the first hop is decorative. The second is DNS rebinding: a hostname can resolve to a public address during the check and to an internal address moments later when the fetch happens. Both are ordinary techniques, and both forced the fix into the request handler rather than into a configuration allowlist.
Why the blast radius exceeds the endpoint
Consider what a training server talks to. An MLflow tracking server holds database credentials for its backend store, credentials for the artefact store, and often a token for the model registry. Under Kubernetes it frequently carries a mounted service account token at the standard path. None of that is exotic. It is the ordinary shape of a deployment.
A forged outbound request from that process can therefore reach:
- the instance metadata endpoint, where cloud workloads without hardened metadata access are concerned;
- internal Kubernetes API addresses, where the mounted service account token becomes worth stealing;
- artefact storage administrative endpoints that trust the source address;
- metrics and admin ports bound to the pod network and never meant to be reachable from outside it. No payload is required. A GET request is enough to return a signed URL or a short-lived token in the response body, and that body travels back through the webhook call the attacker initiated. This is the part defenders underestimate: the attacker needs one read, not a shell.
The provider-key problem next door
A second exposure follows the same architecture without needing this CVE at all. MLflow supports model gateways that call third-party providers, and the gateway configuration carries API keys. Earlier releases in the same line shipped fixes where an api_key field would accept an environment-variable reference, resolve it server-side and then transmit the resolved value to whatever api_base the configuration named. If an attacker can write gateway configuration, through an exposed tracking server, a shared experiment or a compromised service account with registry write rights, the provider key leaves the building with no SSRF involved.
Read together, the two issues describe one property: MLflow both stores secrets and makes outbound calls on behalf of anyone who can reach it. The 3.15.0 release addressed the second half. The first half is a configuration problem, and it belongs to the operator.
What to do beyond upgrading
Upgrade to 3.15.0, then assume the same class of bug returns, because a project this size will ship another one.
- Fix egress. The server needs its database, its artefact store and its model providers. It does not need the metadata service. An egress policy denying link-local addresses and non-allowlisted private ranges removes most of the value of any future SSRF, including the ones nobody has filed yet.
- Harden metadata access. Require IMDSv2 with a hop limit of one where that option exists, or disable the metadata service on the workload network namespace if the platform permits it.
- Rotate what the service can see. If the tracking server was internet-reachable and unpatched, treat the database password, the artefact store keys and the registry token as disclosed. Absence of evidence in application logs is weak here, because a forged webhook call looks like a legitimate delivery.
- Audit gateway configuration. Look for api_key values that reference environment variables and for api_base values pointing somewhere unexpected, then rotate those provider keys.
- Close the front door. The tracking server is an internal tool. Put it behind single sign-on at a reverse proxy rather than leaving it beside the demo deployments that make standing one up so easy.
Reading the population honestly
Commercial scanning of this CVE began shortly after publication, and broad fingerprinting put exposed MLflow-related assets in the tens of thousands. Treat that as an upper bound rather than a census. A fingerprint counts anything answering with the expected characteristics, including development instances, containers left running on a laptop and honeypots researchers spin up to watch what arrives. The direction of the number is the useful part. A model registry stopped being a niche tool some time ago, and the population of reachable instances grew faster than the habit of putting one behind a login.
The uncomfortable conclusion is that for many teams the real exposure was never the webhook. It was that an internal build tool holding credentials for the entire model pipeline answered on a public address, and nobody had written down that it did.
References
- GitHub Security Advisory GHSA-7gwp-5pfp-969j, MLflow webhook endpoint missing authentication, fixed in 3.15.0.
- NVD record for CVE-2026-64849.
- MLflow documentation for the AI Gateway, describing api_base and api_key handling for provider connections.
Top comments (0)