MLflow CVE-2026-64849 carries a CVSS v3.1 base score of 9.3, sits in CISA’s Known Exploited Vulnerabilities catalog, and was published by India’s CERT-In as vulnerability note CIVN-2026-0416 on 20 August 2026. The part worth your time is not MLflow. It is the shape of the bug. A URL was validated once, as a string, and then handed to an HTTP client that followed a redirect and resolved the hostname again. The check and the use looked at two different destinations. If your product accepts a URL from a user and fetches it later, for a webhook, a callback, a link preview, an image import or a PDF render, you have this shape in your codebase, and the only question that matters is whether you pin the address you validated or whether you validate text and let the client go wherever it is sent.
Key findings
- Validate-then-fetch is a time-of-check-to-time-of-use bug, not a validation bug. The validator was correct about the string it inspected. It was never consulted about the address the socket actually reached.
- The published record names two different files, which is the whole story. Per NVD,
_validate_webhook_url()inmlflow/utils/validation.pychecked the original URL, whilemlflow/webhooks/delivery.pyfollowed redirects and re-resolved the hostname without pinning the validated address. - This is a web SSRF in a machine learning platform, not an AI vulnerability. No model, no prompt, no inference path appears anywhere in the bug. It is AI and ML infrastructure, and it is found with ordinary web and API test cases.
- The matching test case is public and already written: OWASP WSTG v4.2, WSTG-INPV-19. Its Common Filter Bypass section names registering a domain that resolves to 127.0.0.1, and its reference list includes an item titled Abusing the AWS Metadata Service Using SSRF Vulnerabilities.
- CERT-In published this as CIVN-2026-0416 on 20 August 2026 at Critical severity. For Indian teams that is a nationally recognised reference to attach to an out-of-cycle upgrade request.
This post is written by Rathnakara GN, who leads penetration testing at Cybersecify, with Ashok Kamat. It analyses a publicly disclosed issue using the published record. We did not test MLflow, we have no client relationship to this software, and nothing here is reproduction detail. The endpoint path and the validator function name appear below because both are already in the CVE record and the vendor advisory, and a defender cannot check their own code against a pattern they are not allowed to see named.
What the record actually says
The primary sources agree, which is worth noting because they were written by different parties.
MLflow shipped version 3.15.0 on 31 July 2026. Its release notes contain the line “[Model Registry] Fix DNS-rebinding SSRF bypass in webhook delivery (#24258, @PattaraS)”.
The vendor advisory is GHSA-7gwp-5pfp-969j, titled “Unauthenticated full-read SSRF in MLflow webhook delivery: _validate_webhook_url bypassed via unvalidated HTTP redirects (and DNS rebinding)”. It rates the issue Critical and names the affected range as everything before 3.15.0.
The NVD entry for CVE-2026-64849 was published on 17 August 2026. Its description reads: “MLflow is an open source AI engineering platform for agents, large language models, and machine learning models. Prior to 3.15.0, the unauthenticated POST /api/2.0/mlflow/webhooks/{id}/test endpoint calls _validate_webhook_url() in mlflow/utils/validation.py only for the original URL while mlflow/webhooks/delivery.py follows redirects and re-resolves the hostname without pinning the validated address, allowing attackers to reach internal or cloud metadata services and receive response_status and response_body.” The score is 9.3 Critical, vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N, assigned by GitHub as the CVE Numbering Authority, and the weakness is CWE-918, Server-Side Request Forgery.
CISA added it to the Known Exploited Vulnerabilities catalog on 19 August 2026 under the name “MLflow Server-Side Request Forgery Vulnerability”, with a remediation due date of 2 September 2026 for the agencies that catalog binds. CISA’s own one-line description: “MLflow contains a server-side request forgery vulnerability that can allow attackers to reach internal or cloud metadata services and receive response_status and response_body.” The catalog records known ransomware campaign use as Unknown.
On exploitation in the wild, the attribution is single-origin and we are going to keep it that way. The security firm watchTowr stated that within hours of CVE assignment, watchTowr Intel via Attacker Eye, its global honeypot network, observed attackers targeting cloud-hosted MLflow systems in an attempt to extract credentials and secrets. Several newsrooms carried that statement. They are reporting the same observation from the same source, so treat it as one line of evidence, corroborated structurally by the fact that CISA placed the CVE in a catalog reserved for vulnerabilities with evidence of active exploitation.
Two claims that circulated in secondary coverage, about post-compromise cryptomining and the creation of cloud identities for persistence, we could not trace to a primary source, so they are not in this post.
Why validate-then-fetch is a TOCTOU bug
Read the mechanism with the product name removed and it stops looking like an MLflow problem.
A caller supplies a URL. A function inspects that URL, resolves the hostname, sees a public address, and returns true. The URL string is then passed to an HTTP client. The client parses the string, resolves the hostname itself, opens a connection, and follows whatever redirects the server sends back, resolving each new hostname in turn.
Nothing in that sequence carries the approved address forward. The validator produced a boolean about a string. The client made an independent decision about where to connect. The two are joined only by the text of the URL, and the text of a URL is not a destination. It is a name that gets turned into a destination, twice, by two different pieces of code, at two different moments.
That is a textbook time-of-check-to-time-of-use flaw, and naming it correctly is what makes the fix obvious. The classic TOCTOU examples in security training are filesystem races, where a program checks a path and then opens it, and the path is swapped in between. This is the same defect with DNS and HTTP redirects playing the role of the swap. Two independent mechanisms can perform the swap: an attacker-controlled server can answer with a redirect to an internal address, or an attacker-controlled DNS record can return a public address on the first lookup and an internal one on the second. The MLflow advisory names both.
The reason this survives code review is that both halves look correct in isolation. The validator is a tidy function with a clear name and a unit test. The delivery path is three lines of a standard HTTP library with sensible defaults, and following redirects is the default in most HTTP clients precisely because most callers want it. The defect lives in the space between two reasonable pieces of code, which is exactly the space that a review of either file will not cover.
The category error worth avoiding
Vulnerability databases describe MLflow, in the first sentence of the CVE record, as “an open source AI engineering platform for agents, large language models, and machine learning models.”
That sentence will push a reader toward filing this under an AI risk taxonomy, and it should not. Walk the bug and count the AI: there is no model, no prompt, no inference call, no training data, no embedding store and no agent anywhere in the path. There is a webhook feature, a URL string, a validator, an HTTP client and a redirect. Those are the constituent parts of a web application from 2010.
The useful distinction for a CTO deciding where testing budget goes is between the model layer and the infrastructure around it. The model layer is where prompt handling, output handling, tool invocation and data flow into and out of a model live, and that layer genuinely needs test cases written for it, which is what an AI application pentest is for. Everything else in an ML stack is a tracking server, a registry, an artifact store, a scheduler, a queue, a set of APIs and a pile of webhooks. That is API and cloud surface, and it is tested with API and cloud test cases.
Getting this backwards costs money in both directions. Buying model-layer testing for a tracking server produces a report about a threat model the component does not have. Assuming that because a system is “AI” it needs only AI testing leaves the ordinary web surface, which is where this 9.3 lived, untested. The MLflow issue is a clean argument for scoping AI systems as what they mostly are, which is a lot of conventional infrastructure with a model somewhere inside it.
Where this shape lives in an ordinary SaaS product
The shape is not rare. Any feature where a user supplies a URL that your servers later fetch has it. The recurring ones in a Series A SaaS product:
- Outbound webhooks and callback URLs. The customer types a URL, you POST to it, and there is usually a “send test event” button that returns the response so the customer can debug. That button converts a blind primitive into a full read.
- Link previews and unfurls. Anywhere a pasted URL becomes a card with a title and an image.
- Import by URL. Avatars, logos, CSV imports, document imports, “add from URL” in any uploader.
- HTML to PDF and screenshot rendering. The renderer is an HTTP client with a browser attached, and it will fetch subresources you did not think about.
- OAuth, OIDC and SAML metadata discovery. Tenant-supplied issuer URLs, JWKS endpoints and metadata documents are all fetched server side.
- RSS, sitemap and feed importers, and any integration that polls a customer-supplied endpoint.
- Server-side proxies for third-party APIs, where the customer configures the base URL.
The severity multiplier is the environment. A workload running in a cloud instance sits next to a metadata service on a link-local address that hands out credentials for the workload’s identity to anything that asks from the right network position. That is why the CVSS vector for this issue has scope changed and confidentiality high: the vulnerable component and the impacted component are not the same thing. The webhook feature was the way in. The cloud identity was the prize.
What to check in your own code
Work through this in order. It does not require knowing anything about MLflow.
1. Build the inventory. Grep for the HTTP client constructors in your language, then trace backwards from each call site to see whether the URL, or any part of it, can be influenced by a value that arrived from outside your trust boundary. Include values that came from a database, if the database got them from a user. Most teams find more call sites than they expected, and the surprising ones are usually in a background worker rather than in the request path.
2. For each one, answer the redirect question. Does the client follow redirects? In most standard libraries the answer is yes by default. If it does, is every hop validated with the same rules as the first, or only the first?
3. Answer the pinning question. This is the one that decides the bug. Between the moment your validator approved an address and the moment the socket connected, was the hostname resolved again? If the answer is yes, or if you do not know, your validation is advisory rather than binding. The correct pattern is to resolve once, make the decision about the resolved IP addresses, and then connect to a chosen address directly, so that no second resolution can occur.
4. Answer the reflection question. How much of the upstream response reaches the caller? Status code, body, headers, response time and error message text are all channels. A feature that returns the body is a full-read primitive. A feature that returns only a boolean success flag still leaks internal network structure through timing and error differences, which is the blind variant.
5. Check the allowlist direction. A denylist of internal ranges is the wrong shape, because the space of ways to express an internal address is large and the space of destinations your product is supposed to reach is small. An allowlist of permitted hosts, resolved and pinned, is the shape that holds.
6. Check egress at the network layer. Application-level validation is one control. The workload’s own egress policy is a second, independent one, and it is the one that still works when the first has a bug. A tracking server has no legitimate reason to open a connection to a link-local metadata address. Where your cloud provider offers a stricter metadata service mode that requires a session token, turn it on.
Controls 3 and 6 are the ones that survive a refactor. Controls written as string checks tend to decay, because the next engineer adds a feature, uses a different HTTP client, and the check does not travel with it.
The test case, and the honest limit of the mapping
The test case for this class is not new and not ours. It is OWASP Web Security Testing Guide v4.2, test case WSTG-INPV-19, Testing for Server-Side Request Forgery, and it is worth ninety seconds of a buyer’s time to open it and read two things.
The first is its Common Filter Bypass section, which is a list of ways an attacker gets a validator to approve a destination it should have rejected. It covers alternative encodings of a loopback address, URL parser confusion using the userinfo separator and the fragment character, and, most directly relevant here, “Registering your own domain that resolves to 127.0.0.1”. That is the same manoeuvre as a validated public hostname whose second resolution, or whose redirect target, points inward. The failure mode was documented in a public testing guide before the CVE existed.
The second is its References list, which includes an item titled “Abusing the AWS Metadata Service Using SSRF Vulnerabilities”. That is the attack path CISA describes in its own catalog entry for this CVE, word for word in substance: reach internal or cloud metadata services and receive the response.
So the mapping is unusually easy to verify. The weakness class in the CVE record is CWE-918. The OWASP test case for CWE-918 is WSTG-INPV-19. That test case’s own documentation names both the bypass technique and the target. You do not have to take a vendor’s word for the mapping, which is the point of naming it this precisely. Our methodology page lists the standards our web and API testing works against, WSTG v4.2 among them.
The limit, stated in the same breath as the coverage, because it belongs there. Running WSTG-INPV-19 against an application is not a guarantee of finding every instance of this pattern in a large codebase. Outbound-fetch call sites hide in background workers, in third-party SDKs and in features that are not reachable from the UI, and no time-boxed engagement enumerates all of them with certainty. What is certain is the other direction: a scope that excludes outbound-fetch features cannot find this at all. That is the practical reason to name webhooks, callbacks, imports and rendering surfaces explicitly when you write a scope, rather than assuming the word “application” covers them.
The India angle: CERT-In CIVN-2026-0416
CERT-In published vulnerability note CIVN-2026-0416, “Server-Side Request Forgery Vulnerability in MLflow”, with an original issue date of 20 August 2026 and a severity rating of Critical. It lists MLflow versions prior to 3.15.0 as affected. Its overview states that a vulnerability in MLflow enables unauthenticated attackers to execute Server-Side Request Forgery attacks and retrieve sensitive server information, and its description quotes the impact as follows: “Successful exploitation of this vulnerability could allow an unauthenticated attacker to conduct Server-Side Request Forgery (SSRF) attacks and gain sensitive information on the targeted server.” The solution it gives is to apply the vendor update, and it points at the GitHub advisory.
Two things to be clear about. This is India’s national CERT publishing on a globally used open source product, not an India breach and not an India-specific incident. And the note adds no technical detail that the vendor advisory does not already carry.
What it does add is standing. If you run MLflow inside an Indian company and you are trying to get an out-of-cycle upgrade past a change advisory board, a CERT-In vulnerability note is a reference your risk, audit and compliance functions already recognise, and it is shorter to cite than a GitHub advisory URL. That is a small thing that saves a real argument.
We are not CERT-In empanelled and do not claim to be. We cite CERT-In as a primary source the same way we cite NVD or OWASP.
Scoping this, if you are buying testing
If you want this class covered, the scope needs to say so. “Test our web app” does not reliably reach a webhook delivery worker. A scope that names the outbound-fetch features, the webhook sender, the import paths, the renderer, the metadata discovery endpoints, is what puts them in front of a tester.
Our Startup Pentest is INR 74,999 and covers one scope over 5 business days. The Growth Pentest is INR 1,79,999 and covers two scopes over 10 business days, with SOC 2 and ISO 27001 evidence mapping. Scopes run sequentially by default, so each additional scope adds 5 business days. Parallel testing is available on request from the third scope onward on Growth, and it is an option rather than a guarantee.
For an ML platform specifically, the honest scoping conversation is usually two scopes rather than one: the application and its APIs, including every outbound-fetch feature, and the cloud environment the workload runs in, because the second is what determines whether an SSRF finding is a curiosity or a credential disclosure. Our API pentest and cloud pentest pages describe what each covers.
The one sentence to take away
Validation that returns a verdict about a string is not validation. Validation that returns an address, and a client that connects to that address and nothing else, is.
Want to see how we report AI findings? Our sample penetration test report is published in full, no email gate. For what an AI scope covers and where it stops, see AI and API penetration testing.
Sources
- NVD, CVE-2026-64849 record, published 17 August 2026, CVSS v3.1 base score 9.3, CWE-918.
- GitHub Security Advisory GHSA-7gwp-5pfp-969j, MLflow, Critical, affected versions before 3.15.0.
- MLflow v3.15.0 release notes, published 31 July 2026, “[Model Registry] Fix DNS-rebinding SSRF bypass in webhook delivery (#24258, @PattaraS)”.
- CISA Known Exploited Vulnerabilities catalog, CVE-2026-64849 added 19 August 2026, due date 2 September 2026, known ransomware campaign use Unknown.
- CERT-In Vulnerability Note CIVN-2026-0416, “Server-Side Request Forgery Vulnerability in MLflow”, original issue date 20 August 2026, severity Critical.
- OWASP Web Security Testing Guide v4.2, WSTG-INPV-19, Testing for Server-Side Request Forgery, including its Common Filter Bypass section and References list.
- watchTowr statement on in-the-wild activity observed via its Attacker Eye honeypot network, as carried by SecurityWeek, The Hacker News and Decipher. Single origin, treated as one source.
All URLs and figures were checked against the sources named above on 5 September 2026.