VYPR
Critical severity9.1NVD Advisory· Published Jun 3, 2026

CVE-2026-4035

CVE-2026-4035

Description

MLflow AI Gateway secrets can leak environment credentials via resolved environment variables, potentially leading to artifact poisoning and RCE.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

MLflow AI Gateway secrets can leak environment credentials via resolved environment variables, potentially leading to artifact poisoning and RCE.

Vulnerability

Versions of mlflow/mlflow prior to 3.11.0 contain a vulnerability where the api_key field in gateway secrets can resolve environment variables. This occurs when the MLflow server's environment is used at runtime to resolve $ENV_VAR references within secrets. This functionality is enabled for the legacy YAML-config gateway when running mlflow gateway start [1].

Exploitation

An attacker can exploit this vulnerability by configuring a malicious gateway secret with an environment variable reference. When the MLflow gateway processes this secret and sends it in provider authentication headers to a configured upstream api_base, the environment variable's value is resolved and exfiltrated. This can be achieved by low-privileged authenticated users in basic-auth deployments or by unauthenticated users in default deployments without basic-auth [2].

Impact

Successful exploitation allows an attacker to exfiltrate sensitive server-side environment credentials to an attacker-controlled endpoint. This can include critical credentials like cloud artifact credentials (e.g., AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY), which could subsequently lead to artifact poisoning and cross-boundary code execution in downstream environments [2].

Mitigation

The vulnerability is fixed in mlflow/mlflow version 3.11.0. Users are advised to upgrade to this version or later. No workarounds are specified in the available references, and the issue is not listed as part of the KEV catalog [1, 2].

AI Insight generated on Jun 3, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

1
4a3f2f720cb4

Gate env-var API key resolution behind MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV (#21544)

https://github.com/mlflow/mlflowTomuHirataMar 10, 2026via nvd-ref
5 files changed · +30 4
  • mlflow/environment_variables.py+8 0 modified
    @@ -632,6 +632,14 @@ def get(self):
         "MLFLOW_GATEWAY_RATE_LIMITS_STORAGE_URI", str, None
     )
     
    +#: If True, the gateway will attempt to resolve API keys from environment variables
    +#: (``$``-prefixed values). This is only enabled for the legacy YAML-config gateway
    +#: (``mlflow gateway start``).
    +#: (default: ``False``)
    +MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV = _BooleanEnvironmentVariable(
    +    "MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV", False
    +)
    +
     #: If True, the gateway will attempt to resolve API keys from local file paths.
     #: This is only enabled for the legacy YAML-config gateway (``mlflow gateway start``).
     #: (default: ``False``)
    
  • mlflow/gateway/app.py+3 1 modified
    @@ -22,6 +22,7 @@
     from mlflow.environment_variables import (
         MLFLOW_GATEWAY_CONFIG,
         MLFLOW_GATEWAY_RATE_LIMITS_STORAGE_URI,
    +    MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV,
         MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE,
     )
     from mlflow.exceptions import MlflowException
    @@ -465,7 +466,8 @@ def create_app_from_path(config_path: str | Path) -> GatewayAPI:
         """
         Load the path and generate the GatewayAPI app instance.
         """
    -    # Enable file-based API key resolution for the legacy YAML-config gateway
    +    # Enable env-var and file-based API key resolution for the legacy YAML-config gateway
    +    os.environ[MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV.name] = "true"
         os.environ[MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE.name] = "true"
         config = _load_gateway_config(config_path)
         return create_app_from_config(config)
    
  • mlflow/gateway/config.py+7 3 modified
    @@ -11,7 +11,10 @@
     from pydantic import ConfigDict, ValidationError, field_validator, model_validator
     from pydantic.json import pydantic_encoder
     
    -from mlflow.environment_variables import MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE
    +from mlflow.environment_variables import (
    +    MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV,
    +    MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE,
    +)
     from mlflow.exceptions import MlflowException
     from mlflow.gateway.base_models import ConfigModel, LimitModel, ResponseModel
     from mlflow.gateway.constants import (
    @@ -301,6 +304,7 @@ def _resolve_api_key_from_input(api_key_input):
         Input formats accepted:
     
         - environment variable name that stores the api key (prefixed with ``$``)
    +      (only when ``MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV`` is ``true``)
         - Path to a file as a string which will have the key loaded from it
           (only when ``MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE`` is ``true``)
         - the api key itself
    @@ -311,8 +315,8 @@ def _resolve_api_key_from_input(api_key_input):
                 "variable key, a path to a file containing the api key, or the api key itself"
             )
     
    -    # try reading as an environment variable
    -    if api_key_input.startswith("$"):
    +    # try reading as an environment variable (only for legacy YAML-config gateway)
    +    if api_key_input.startswith("$") and MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV.get():
             env_var_name = api_key_input[1:]
             if env_var := os.environ.get(env_var_name):
                 return env_var
    
  • mlflow/gateway/runner.py+2 0 modified
    @@ -8,6 +8,7 @@
     
     from mlflow.environment_variables import (
         MLFLOW_GATEWAY_CONFIG,
    +    MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV,
         MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE,
     )
     from mlflow.gateway import app
    @@ -76,6 +77,7 @@ def start(self) -> None:
                 env={
                     **os.environ,
                     MLFLOW_GATEWAY_CONFIG.name: self.config_path,
    +                MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV.name: "true",
                     MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_FILE.name: "true",
                 },
             )
    
  • tests/gateway/test_gateway_config_parsing.py+10 0 modified
    @@ -77,6 +77,8 @@ def test_assemble_uri_path(paths, expected):
     
     
     def test_api_key_parsing_env(tmp_path, monkeypatch):
    +    # Env-var resolution requires the flag to be enabled
    +    monkeypatch.setenv("MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV", "true")
         monkeypatch.setenv("KEY_AS_ENV", "my_key")
     
         assert _resolve_api_key_from_input("$KEY_AS_ENV") == "my_key"
    @@ -99,6 +101,14 @@ def test_api_key_parsing_env(tmp_path, monkeypatch):
         assert _resolve_api_key_from_input(str(conf_path)) == file_key
     
     
    +def test_api_key_env_resolution_blocked_without_flag(monkeypatch):
    +    monkeypatch.setenv("KEY_AS_ENV", "my_key")
    +    monkeypatch.delenv("MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV", raising=False)
    +
    +    # Without the flag, $-prefixed values are returned as literal strings
    +    assert _resolve_api_key_from_input("$KEY_AS_ENV") == "$KEY_AS_ENV"
    +
    +
     def test_api_key_input_exceeding_maximum_filename_length():
         assert _resolve_api_key_from_input("a" * 256) == "a" * 256
     
    

Vulnerability mechanics

Root cause

"The MLflow gateway incorrectly resolves environment variables within AI Gateway secrets, allowing for credential exfiltration."

Attack vector

An attacker can create or modify gateway secrets to include environment variable references, such as `$ENV_VAR`. When these secrets are used in provider authentication headers for upstream API calls, the MLflow server resolves these references against its own environment. This allows sensitive credentials, like cloud artifact keys, to be sent to an attacker-controlled endpoint. This can be exploited by low-privileged authenticated users or even unauthenticated users in default deployments [ref_id=1].

Affected code

The vulnerability lies within the `_resolve_api_key_from_input` function in `mlflow/gateway/config.py`. The patch modifies this function to check the `MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV` environment variable before attempting to resolve environment variables prefixed with '$' [ref_id=1].

What the fix does

The patch introduces a new environment variable, `MLFLOW_GATEWAY_RESOLVE_API_KEY_FROM_ENV`, which defaults to `False`. This variable must be explicitly set to `true` to enable the resolution of environment variables for API keys in the legacy YAML-config gateway. This change ensures that environment variable resolution is an opt-in feature, preventing accidental leakage of sensitive credentials [ref_id=1].

Preconditions

  • authAttacker must have at least low-privileged authenticated access in basic-auth deployments, or no authentication is required in default deployments.
  • configThe MLflow gateway must be configured to use secrets that can reference environment variables.

Generated on Jun 3, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

2

News mentions

0

No linked articles in our index yet.