Leadership1 distinct publisher3 min readUpdated
A GitHub advisory describes an unauthenticated, full-read SSRF in the default MLflow tracking server that reaches the cloud metadata endpoint and reflects the response back to the caller.
The Board Room · Leadership desk

Compiled by The Board RoomSomething wrong?How this is made
A security advisory on GitHub describes an unauthenticated, full-read server-side request forgery in the default MLflow tracking server, one that reaches cloud metadata endpoints and returns the response straight to the caller [1][6]. The interesting part is not the redirect bug. It is what the default configuration says about how ML tooling was deployed during the last two years: as a lab convenience, not as production infrastructure.
Start with the defaults. Run `mlflow server` and you get no authentication, a SQLite backend, and a model-registry webhooks API that is exposed with no auth in front of it [1]. The only authorization for webhooks lives in an optional auth plugin that is not loaded by default [7]. So the webhook endpoints are reachable by anyone who can reach the server.
The maintainers did try. Version 3.10.0 added an SSRF guard, `_validate_webhook_url`, which resolves the webhook hostname and rejects any non-public IP, blocking loopback, RFC1918, link-local and metadata addresses [3][15]. It works against the obvious attack. In the researcher's negative control, a webhook pointed at `http://127.0.0.1:6379/` was rejected with a 400 [10].
The problem is that the guard validates but pins nothing [4]. Delivery follows HTTP redirects, because the request is not sent with `allow_redirects=False`, and the validated IP is never carried into the connection [4]. The guard re-checks only the original URL, never the redirect target [8]. So an attacker registers a webhook pointing at a public HTTPS host they control, which passes the check, and that host returns a 302 to `http://169.254.169.254/...`; MLflow follows it and never re-validates [5]. Because the synchronous `/test` endpoint reflects the upstream status and body back to the caller, the internal response comes back out [2]. A second path, DNS rebinding, works for the same underlying reason: the guard and the actual connection resolve the name independently with no pinning [9].
In the proof of concept, creating the webhook returned 200 with status ACTIVE, and firing it through the unauthenticated `/test` endpoint returned 200 with the contents of the metadata path in `response_body` [11][12]. The attacker's redirect pointed at `http://169.254.169.254/latest/meta-data/iam/security-credentials/`, the path that vends the IAM role credentials of whatever the server runs as [13]. The researcher confirmed it live against mlflow 3.13.0 on a default SQLite server [14].
Read the chain plainly. No login, one HTTP request to create a webhook, one to fire it, and the server reads its own cloud role credentials aloud [1][11][12]. That is not an exotic exploit. It is the expected outcome when a tool ships with authentication off by default and an experiment tracker ends up holding a cloud identity that can touch storage and model artifacts.
What to watch: whether the fix disables redirect following and pins the validated IP into the connection rather than adding another string check, and whether MLflow moves authentication from an optional plugin to the default posture. For operators, the more useful audit is not this CVE but the inventory question behind it. Find every MLflow, notebook, and vector-store service standing up inside your accounts, and check which of them are exposed unauthenticated while holding an instance role.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Because /test reflects the response body, this is an unauthenticated full-read SSRF on a default server.
A second bypass is DNS rebinding (TOCTOU): getaddrinfo in the guard and the requests connect resolve the name independently with no pinning.
The default MLflow tracking server (mlflow server, no authentication, default SQLite backend) exposes the model-registry webhooks API unauthenticated.
A synchronous POST /api/2.0/mlflow/webhooks/{id}/test endpoint returns the upstream response status and body to the caller.
The SSRF guard _validate_webhook_url, added in PR #20747 and shipped in 3.10.0, resolves the webhook hostname and rejects non-public IPs, blocking RFC1918, loopback, link-local and metadata addresses.
The guard validates but pins nothing: delivery follows HTTP redirects (no allow_redirects=False) and the resolved/validated IP is never carried into the connection.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Strong technical evidence, single source
The advisory supplies named source files and quoted code for both the guard and the delivery path, a negative control that demonstrates the guard is active, and a full request/response transcript in which /test reflects a body fetched by the server, all stated as confirmed live against mlflow==3.13.0. Evidence falls short of maximal because it rests on one publisher with no independent reproduction and because the cloud-metadata outcome was simulated with a local secret rather than a real IMDS response.
No exposure or exploitation data supplied
The cluster contains no count or estimate of exposed MLflow tracking servers, no telemetry, no observed exploitation, and no affected/fixed version distribution. The only adoption-adjacent facts are the advisory publication and the referenced fix PR, which speak to vendor acknowledgement rather than deployment or uptake scale, so no adoption value can be measured without inventing figures.
Mechanism proven, credential theft extrapolated
The mechanism claims are matched by the evidence, so the gap is small. It is positive because the framing that the server hands out cloud credentials outruns the demonstration: the researcher explicitly had no cloud deployment and substituted a local secret file for the metadata response, and no exposure or exploitation data supports the implied breadth of real-world credential loss.
Researcher credit and vendor disclosure framing
The sole source is the vendor-hosted advisory for the affected project, published alongside its own fix PR, which gives the publisher an interest in presenting the issue as identified and remediated. The text also carries an explicit discovery-priority arbitration between a private reporter and an independent public finder, a reputational incentive that shapes emphasis. These are visible, disclosed incentives rather than hidden commercial ones, so the score is moderate rather than high.
High on mechanism, low on real-world impact
Confidence in the technical mechanism is high given quoted code, a negative control and a version-pinned live reproduction. It is held down by single-publisher sourcing with no independent verification, the absence of any exposure or exploitation data, and the fact that the headline cloud-credential impact was simulated, leaving the severity claim less certain than the vulnerability claim.
security
Akrites switches on in September with 20-odd members and a one-to-10 engineer donation band1 distinct publisher
build
AI-written code fails the same four ways, and every gate you own reports green1 distinct publisher
build
Grok 4.6 lands in Copilot two days after launch, and the model picker becomes a procurement problem1 distinct publisher
security
Windows 11's secure kernel trusts a RAM chip that never checks who is writing to it1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
1 article · August 20, 2026