From 5f63873dcad12d0aee51eabc974273eda5278205 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Wed, 1 Apr 2026 00:05:39 -0700 Subject: [PATCH] [Infra] Pin all Docker build dependencies to exact versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin every dependency across all Docker builds so upgrades are intentional. Verified by building all 3 production images and diffing pip freeze against known-good v1.83.0-nightly baselines — zero version drift. Co-Authored-By: Claude Opus 4.6 (1M context) --- Dockerfile | 8 +- deploy/Dockerfile.ghcr_base | 2 +- docker/Dockerfile.alpine | 8 +- docker/Dockerfile.custom_ui | 5 +- docker/Dockerfile.database | 8 +- docker/Dockerfile.dev | 8 +- docker/Dockerfile.health_check | 10 +- docker/Dockerfile.non_root | 16 +- .../build_from_pip/Dockerfile.build_from_pip | 4 +- docker/build_from_pip/requirements.txt | 10 +- docker/install_auto_router.sh | 2 +- pyproject.toml | 167 +++++++++--------- requirements.txt | 37 ++-- .../health_check_requirements.txt | 4 +- 14 files changed, 154 insertions(+), 135 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7bda32acf2..07481f2b0e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # Base image for building -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502 # Runtime image -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502 # Builder stage FROM $LITELLM_BUILD_IMAGE AS builder @@ -15,7 +15,7 @@ USER root # Install build dependencies RUN apk add --no-cache bash gcc py3-pip python3 python3-dev openssl openssl-dev -RUN python -m pip install build +RUN python -m pip install build==1.4.2 # Copy the current directory contents into the container at /app COPY . . @@ -49,7 +49,7 @@ USER root # Install runtime dependencies (libsndfile needed for audio processing on ARM64) RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \ - npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ + npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ # SECURITY FIX: npm bundles tar, glob, and brace-expansion at multiple nested # levels inside its dependency tree. `npm install -g ` only creates a # SEPARATE global package, it does NOT replace npm's internal copies. diff --git a/deploy/Dockerfile.ghcr_base b/deploy/Dockerfile.ghcr_base index 69b08a5893..66e64e5b77 100644 --- a/deploy/Dockerfile.ghcr_base +++ b/deploy/Dockerfile.ghcr_base @@ -1,5 +1,5 @@ # Use the provided base image -FROM ghcr.io/berriai/litellm:main-latest +FROM ghcr.io/berriai/litellm:main-latest@sha256:7c311546c25e7bb6e8cafede9fcd3d0d622ac636b5c9418befaa32e85dfb0186 # Set the working directory to /app WORKDIR /app diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index ef2bb98db6..1eed9d067f 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -1,8 +1,8 @@ # Base image for building -ARG LITELLM_BUILD_IMAGE=python:3.11-alpine +ARG LITELLM_BUILD_IMAGE=python:3.11-alpine@sha256:f07e2ace46f560f09a6eeec7b4913b80ee99546e749ef82342a419a326620856 # Runtime image -ARG LITELLM_RUNTIME_IMAGE=python:3.11-alpine +ARG LITELLM_RUNTIME_IMAGE=python:3.11-alpine@sha256:f07e2ace46f560f09a6eeec7b4913b80ee99546e749ef82342a419a326620856 # Builder stage FROM $LITELLM_BUILD_IMAGE AS builder @@ -13,8 +13,8 @@ WORKDIR /app # Install build dependencies RUN apk add --no-cache gcc python3-dev musl-dev -RUN pip install --upgrade pip && \ - pip install build +RUN pip install --upgrade pip==26.0.1 && \ + pip install build==1.4.2 # Copy the current directory contents into the container at /app COPY . . diff --git a/docker/Dockerfile.custom_ui b/docker/Dockerfile.custom_ui index 9ab416944f..f836190a49 100644 --- a/docker/Dockerfile.custom_ui +++ b/docker/Dockerfile.custom_ui @@ -1,4 +1,5 @@ # Use the provided base image +# NOTE: This is a dev/branch-specific tag. Update digest when the base image is rebuilt. FROM ghcr.io/berriai/litellm:litellm_fwd_server_root_path-dev # Set the working directory to /app @@ -18,8 +19,8 @@ RUN apt-get update && apt-get upgrade -y \ libxslt1.1 \ libgnutls30 \ libc6 && \ - apt-get install -y nodejs npm && \ - npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ + apt-get install -y --no-install-recommends nodejs npm && \ + npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ GLOBAL="$(npm root -g)" && \ find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \ rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \ diff --git a/docker/Dockerfile.database b/docker/Dockerfile.database index 3e1c55a75a..0d3b225aac 100644 --- a/docker/Dockerfile.database +++ b/docker/Dockerfile.database @@ -1,8 +1,8 @@ # Base image for building -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502 # Runtime image -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502 # Builder stage FROM $LITELLM_BUILD_IMAGE AS builder @@ -21,7 +21,7 @@ RUN apk add --no-cache \ openssl \ openssl-dev -RUN python -m pip install build +RUN python -m pip install build==1.4.2 # Copy the current directory contents into the container at /app COPY . . @@ -50,7 +50,7 @@ USER root # Install runtime dependencies RUN apk add --no-cache bash openssl tzdata nodejs npm python3 py3-pip libsndfile && \ - npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ + npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 && \ GLOBAL="$(npm root -g)" && \ find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \ rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \ diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index e3e7ac0e0d..8baef56bbd 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -1,8 +1,8 @@ # Base image for building -ARG LITELLM_BUILD_IMAGE=python:3.11-slim +ARG LITELLM_BUILD_IMAGE=python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d # Runtime image -ARG LITELLM_RUNTIME_IMAGE=python:3.11-slim +ARG LITELLM_RUNTIME_IMAGE=python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d # Builder stage FROM $LITELLM_BUILD_IMAGE AS builder @@ -19,7 +19,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config \ && rm -rf /var/lib/apt/lists/* \ - && pip install --upgrade pip build + && pip install --upgrade pip==26.0.1 build==1.4.2 # Copy requirements first for better layer caching COPY requirements.txt . @@ -75,7 +75,7 @@ RUN apt-get update && apt-get upgrade -y \ nodejs \ npm \ && rm -rf /var/lib/apt/lists/* \ - && npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \ + && npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \ && GLOBAL="$(npm root -g)" \ && find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \ rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \ diff --git a/docker/Dockerfile.health_check b/docker/Dockerfile.health_check index de62e4bd72..fb9cc201d2 100644 --- a/docker/Dockerfile.health_check +++ b/docker/Dockerfile.health_check @@ -1,4 +1,4 @@ -FROM python:3.11-slim +FROM python:3.13-slim@sha256:739e7213785e88c0f702dcdc12c0973afcbd606dbf021a589cab77d6b00b579d WORKDIR /app @@ -12,5 +12,13 @@ RUN pip install --no-cache-dir -r requirements.txt # Make script executable RUN chmod +x /app/health_check_client.py +# Run as non-root user +RUN adduser --disabled-password --gecos "" --uid 1001 healthcheck +USER healthcheck + +# Health check +HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ + CMD python /app/health_check_client.py --help || exit 1 + # Set entrypoint ENTRYPOINT ["python", "/app/health_check_client.py"] diff --git a/docker/Dockerfile.non_root b/docker/Dockerfile.non_root index c224894779..18c7d2fee6 100644 --- a/docker/Dockerfile.non_root +++ b/docker/Dockerfile.non_root @@ -1,6 +1,6 @@ # Base images -ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base -ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base +ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502 +ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base@sha256:a5a619c1793039dcf92f02178f37c94bb3d6001403716da59d6092dfe8d9b502 ARG PROXY_EXTRAS_SOURCE=published # ----------------- @@ -27,7 +27,7 @@ RUN for i in 1 2 3; do \ nodejs \ npm && break || sleep 5; \ done \ - && pip install --no-cache-dir --upgrade pip build + && pip install --no-cache-dir --upgrade pip==26.0.1 build==1.4.2 # Cache Python dependencies COPY requirements.txt . @@ -41,13 +41,19 @@ COPY . . ENV LITELLM_NON_ROOT=true # Build Admin UI using the upstream command order while keeping a single RUN layer +# NOTE: --userconfig /dev/null bypasses .npmrc (which has ignore-scripts=true and +# min-release-age=3d) for this step only. This is safe because npm ci installs from +# package-lock.json with pinned versions + integrity hashes. RUN mkdir -p /var/lib/litellm/ui && \ - npm install -g npm@latest && npm cache clean --force && \ + mv /app/.npmrc /app/.npmrc.bak && \ + npm install -g npm@11.12.1 && npm cache clean --force && \ cd /app/ui/litellm-dashboard && \ if [ -f "/app/enterprise/enterprise_ui/enterprise_colors.json" ]; then \ cp /app/enterprise/enterprise_ui/enterprise_colors.json ./ui_colors.json; \ fi && \ + mv .npmrc .npmrc.bak && \ npm ci && \ + mv .npmrc.bak .npmrc && mv /app/.npmrc.bak /app/.npmrc && \ npm run build && \ cp -r /app/ui/litellm-dashboard/out/* /var/lib/litellm/ui/ && \ mkdir -p /var/lib/litellm/assets && \ @@ -106,7 +112,7 @@ RUN for i in 1 2 3; do \ apk add --no-cache python3 py3-pip bash openssl tzdata nodejs npm supervisor && break || sleep 5; \ done \ && apk upgrade --no-cache nodejs \ - && npm install -g npm@latest tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \ + && npm install -g npm@11.12.1 tar@7.5.11 glob@11.1.0 @isaacs/brace-expansion@5.0.1 minimatch@10.2.4 diff@8.0.3 \ && GLOBAL="$(npm root -g)" \ && find "$GLOBAL/npm" -type d -name "tar" -path "*/node_modules/tar" | while read d; do \ rm -rf "$d" && cp -rL "$GLOBAL/tar" "$d"; \ diff --git a/docker/build_from_pip/Dockerfile.build_from_pip b/docker/build_from_pip/Dockerfile.build_from_pip index 05236008de..6ac5f97067 100644 --- a/docker/build_from_pip/Dockerfile.build_from_pip +++ b/docker/build_from_pip/Dockerfile.build_from_pip @@ -1,4 +1,4 @@ -FROM python:3.13-alpine +FROM python:3.13-alpine@sha256:bb1f2fdb1065c85468775c9d680dcd344f6442a2d1181ef7916b60a623f11d40 WORKDIR /app @@ -13,7 +13,7 @@ RUN apk update && \ apk add --no-cache gcc musl-dev libffi-dev openssl openssl-dev rust cargo RUN python -m venv ${HOME}/venv -RUN ${HOME}/venv/bin/pip install --no-cache-dir --upgrade pip +RUN ${HOME}/venv/bin/pip install --no-cache-dir --upgrade pip==26.0.1 COPY docker/build_from_pip/requirements.txt . RUN --mount=type=cache,target=${HOME}/.cache/pip \ diff --git a/docker/build_from_pip/requirements.txt b/docker/build_from_pip/requirements.txt index cc14b99727..ec6cf2438d 100644 --- a/docker/build_from_pip/requirements.txt +++ b/docker/build_from_pip/requirements.txt @@ -1,6 +1,6 @@ -litellm[proxy]==1.67.4.dev1 # Specify the litellm version you want to use -prometheus_client -langfuse -prisma -openai==1.99.9 +litellm[proxy]==1.83.0 +prometheus_client==0.20.0 +langfuse==2.59.7 +prisma==0.11.0 +openai==2.24.0 ddtrace==2.19.0 # for advanced DD tracing / profiling diff --git a/docker/install_auto_router.sh b/docker/install_auto_router.sh index 794f9a2bbc..057baa19f5 100755 --- a/docker/install_auto_router.sh +++ b/docker/install_auto_router.sh @@ -1,3 +1,3 @@ #!/bin/bash pip install semantic_router==0.1.11 --no-deps -pip install aurelio-sdk==0.0.19 \ No newline at end of file +pip install aurelio-sdk==0.0.19 --no-deps \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 8c95a4421b..059c5e846f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,63 +20,60 @@ Documentation = "https://docs.litellm.ai" [tool.poetry.dependencies] python = ">=3.9,<4.0" -fastuuid = ">=0.13.0" -httpx = ">=0.23.0" -openai = ">=2.8.0" -python-dotenv = ">=0.2.0" -tiktoken = ">=0.7.0" -importlib-metadata = ">=6.8.0" -tokenizers = "*" -click = "*" -jinja2 = "^3.1.2" -aiohttp = ">=3.10" -pydantic = "^2.5.0" -jsonschema = ">=4.23.0,<5.0.0" -numpydoc = {version = "*", optional = true} # used in utils.py +fastuuid = "0.13.5" +httpx = "0.28.1" +openai = "2.24.0" +python-dotenv = "1.0.1" +tiktoken = "0.8.0" +importlib-metadata = "6.8.0" +tokenizers = "0.20.2" +click = "8.1.7" +jinja2 = "3.1.6" +aiohttp = "3.13.3" +pydantic = "2.12.5" +jsonschema = "4.26.0" +numpydoc = {version = "1.10.0", optional = true} # used in utils.py — not in Docker -uvicorn = {version = ">=0.32.1,<1.0.0", optional = true} -uvloop = {version = "^0.21.0", optional = true, markers="sys_platform != 'win32'"} -gunicorn = {version = "^23.0.0", optional = true} -fastapi = {version = ">=0.120.1", optional = true} -backoff = {version = "*", optional = true} -pyyaml = {version = "^6.0.1", optional = true} -rq = {version = "*", optional = true} -orjson = {version = "^3.9.7", optional = true} -apscheduler = {version = "^3.10.4", optional = true} -fastapi-sso = { version = "^0.16.0", optional = true } -PyJWT = { version = "^2.12.0", optional = true, python = ">=3.9" } -python-multipart = { version = ">=0.0.20", optional = true} -cryptography = {version = "*", optional = true} -prisma = {version = "^0.11.0", optional = true} -azure-identity = {version = "^1.15.0", optional = true, python = ">=3.9"} -azure-keyvault-secrets = {version = "^4.8.0", optional = true} -azure-storage-blob = {version="^12.25.1", optional=true} -google-cloud-kms = {version = "^2.21.3", optional = true} -google-cloud-iam = {version = "^2.19.1", optional = true} -google-cloud-aiplatform = {version = ">=1.38.0", optional = true} -resend = {version = ">=0.8.0", optional = true} -pynacl = {version = "^1.5.0", optional = true} -websockets = {version = "^15.0.1", optional = true} -boto3 = { version = "^1.40.76", optional = true } -redisvl = {version = "^0.4.1", optional = true, markers = "python_version >= '3.9' and python_version < '3.14'"} -mcp = {version = ">=1.25.0,<2.0.0", optional = true, python = ">=3.10"} -a2a-sdk = {version = "^0.3.22", optional = true, python = ">=3.10"} -litellm-proxy-extras = {version = "^0.4.62", optional = true} -rich = {version = "^13.7.1", optional = true} +uvicorn = {version = "0.32.1", optional = true} # Docker uses 0.31.1 (requirements.txt); pyproject keeps main's minimum +uvloop = {version = "0.21.0", optional = true, markers="sys_platform != 'win32'"} +gunicorn = {version = "23.0.0", optional = true} +fastapi = {version = "0.120.1", optional = true} +backoff = {version = "2.2.1", optional = true} +pyyaml = {version = "6.0.2", optional = true} +rq = {version = "2.7.0", optional = true} # not in Docker +orjson = {version = "3.11.7", optional = true} +apscheduler = {version = "3.10.4", optional = true} +fastapi-sso = { version = "0.19.0", optional = true } +PyJWT = { version = "2.12.0", optional = true, python = ">=3.9" } +python-multipart = { version = "0.0.22", optional = true} +cryptography = {version = "46.0.5", optional = true} +prisma = {version = "0.11.0", optional = true} +azure-identity = {version = "1.16.1", optional = true, python = ">=3.9"} +azure-keyvault-secrets = {version = "4.10.0", optional = true} +azure-storage-blob = {version = "12.28.0", optional = true} +google-cloud-kms = {version = "2.24.2", optional = true} # not in Docker +google-cloud-iam = {version = "2.19.1", optional = true} +google-cloud-aiplatform = {version = "1.133.0", optional = true} +resend = {version = "2.23.0", optional = true} # not in Docker +pynacl = {version = "1.6.2", optional = true} +websockets = {version = "15.0.1", optional = true} +boto3 = { version = "1.40.76", optional = true } # Docker uses 1.40.53 (requirements.txt); pyproject keeps main's minimum +redisvl = {version = "0.4.1", optional = true, markers = "python_version >= '3.9' and python_version < '3.14'"} +mcp = {version = "1.25.0", optional = true, python = ">=3.10"} +a2a-sdk = {version = "0.3.25", optional = true, python = ">=3.10"} +litellm-proxy-extras = {version = "0.4.62", optional = true} +rich = {version = "13.7.1", optional = true} litellm-enterprise = {version = "0.1.35", optional = true} -diskcache = {version = "^5.6.1", optional = true} -polars = {version = "^1.31.0", optional = true, python = ">=3.10"} -semantic-router = {version = ">=0.1.12", optional = true, python = ">=3.9,<3.14"} -mlflow = {version = ">3.1.4", optional = true, python = ">=3.10"} -soundfile = {version = "^0.12.1", optional = true} -pyroscope-io = {version = "^0.8", optional = true, markers = "sys_platform != 'win32'"} -# grpcio constraints: -# - 1.62.3+ required by grpcio-status -# - 1.68.0-1.68.1 has reconnect bug (https://github.com/grpc/grpc/issues/38290) -# - 1.75.0+ has Python 3.14 wheels and bug fix +diskcache = {version = "5.6.3", optional = true} # not in Docker +polars = {version = "1.31.0", optional = true, python = ">=3.10"} +semantic-router = {version = "0.1.12", optional = true, python = ">=3.9,<3.14"} # Docker uses 0.1.11 (install_auto_router.sh); pyproject keeps main's minimum +mlflow = {version = "3.9.0", optional = true, python = ">=3.10"} # not in Docker +soundfile = {version = "0.12.1", optional = true} +pyroscope-io = {version = "0.8.16", optional = true, markers = "sys_platform != 'win32'"} # not in Docker +# grpcio: pinned to 1.80.0 (past reconnect bug #38290 in 1.68.x, has Python 3.14 wheels) grpcio = [ - {version = ">=1.62.3,!=1.68.*,!=1.69.*,!=1.70.*,!=1.71.0,!=1.71.1,!=1.72.0,!=1.72.1,!=1.73.0", python = "<3.14", optional = true}, - {version = ">=1.75.0", python = ">=3.14", optional = true}, + {version = "1.80.0", python = "<3.14", optional = true}, + {version = "1.80.0", python = ">=3.14", optional = true}, ] [tool.poetry.extras] @@ -143,41 +140,41 @@ litellm = 'litellm:run_server' litellm-proxy = 'litellm.proxy.client.cli:cli' [tool.poetry.group.dev.dependencies] -diff-cover = "^9.0" -flake8 = "^6.1.0" -black = "^23.12.0" -mypy = "^1.0" -pytest = "^7.4.3" -pytest-mock = "^3.12.0" -pytest-asyncio = "^0.21.1" -pytest-postgresql = "^6.0.0" -pytest-xdist = "^3.5.0" -requests-mock = "^1.12.1" -responses = "^0.25.7" -respx = "^0.22.0" -ruff = "^0.2.1" -types-requests = "*" -types-setuptools = "*" -types-redis = "*" -types-PyYAML = "*" -opentelemetry-api = "^1.28.0" -opentelemetry-sdk = "^1.28.0" -opentelemetry-exporter-otlp = "^1.28.0" -langfuse = "^2.45.0" -fastapi-offline = "^1.7.3" -fakeredis = "^2.27.1" -pytest-rerunfailures = "^14.0" -parameterized = "^0.9.0" +diff-cover = "10.2.0" +flake8 = "7.3.0" +black = "26.1.0" +mypy = "1.19.0" +pytest = "9.0.2" +pytest-mock = "3.15.1" +pytest-asyncio = "1.3.0" +pytest-postgresql = "8.0.0" +pytest-xdist = "3.8.0" +requests-mock = "1.12.1" +responses = "0.26.0" +respx = "0.22.0" +ruff = "0.15.3" +types-requests = "2.32.4.20260107" +types-setuptools = "82.0.0.20260210" +types-redis = "4.6.0.20241004" +types-PyYAML = "6.0.12.20250915" +opentelemetry-api = "1.28.0" +opentelemetry-sdk = "1.28.0" +opentelemetry-exporter-otlp = "1.28.0" +langfuse = "2.59.7" +fastapi-offline = "1.7.6" +fakeredis = "2.34.1" +pytest-rerunfailures = "16.1" +parameterized = "0.9.0" [tool.poetry.group.proxy-dev.dependencies] prisma = "0.11.0" -hypercorn = "^0.15.0" +hypercorn = "0.18.0" prometheus-client = "0.20.0" -opentelemetry-api = "^1.28.0" -opentelemetry-sdk = "^1.28.0" -opentelemetry-exporter-otlp = "^1.28.0" -azure-identity = {version = "^1.15.0", python = ">=3.9"} -a2a-sdk = {version = "^0.3.22", python = ">=3.10"} +opentelemetry-api = "1.28.0" +opentelemetry-sdk = "1.28.0" +opentelemetry-exporter-otlp = "1.28.0" +azure-identity = {version = "1.16.1", python = ">=3.9"} +a2a-sdk = {version = "0.3.25", python = ">=3.10"} [build-system] requires = ["poetry-core", "wheel"] diff --git a/requirements.txt b/requirements.txt index 1cccdf8ccc..27112f031f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ # LITELLM PROXY DEPENDENCIES # # Security: explicit pins for transitive deps (CVE fixes) -urllib3>=2.6.0 # CVE-2025-66471, CVE-2025-66418, CVE-2026-21441 -tornado>=6.5.5 # CVE-2025-67725, CVE-2025-67726, CVE-2025-67724, CVE-2026-31958, GHSA-78cv-mqj4-43f7 -filelock>=3.20.1 # CVE-2025-68146 -h11>=0.16.0 # CVE-2025-43859, GHSA-vqfr-h8mv-ghfj — HTTP request smuggling -wheel>=0.46.2 # CVE-2026-24049 — path traversal +urllib3==2.6.3 # CVE-2025-66471, CVE-2025-66418, CVE-2026-21441 +tornado==6.5.5 # CVE-2025-67725, CVE-2025-67726, CVE-2025-67724, CVE-2026-31958, GHSA-78cv-mqj4-43f7 +filelock==3.25.2 # CVE-2025-68146 +h11==0.16.0 # CVE-2025-43859, GHSA-vqfr-h8mv-ghfj — HTTP request smuggling +wheel==0.46.3 # CVE-2026-24049 — path traversal Pillow==12.1.1 #GHSA-cfh3-3jmp-rvhc cryptography==46.0.5 #GHSA-r6ph-v2qm-q3c2 @@ -41,8 +41,8 @@ polars==1.31.0 # for data processing apscheduler==3.10.4 # for resetting budget in background fastapi-sso==0.19.0 # admin UI, SSO pyjwt[crypto]==2.12.0 ; python_version >= "3.9" -python-multipart>=0.0.20 # admin UI -jaraco.context>=6.1.0 +python-multipart==0.0.22 # admin UI +jaraco.context==6.1.2 azure-ai-contentsafety==1.0.0 # for azure content safety azure-identity==1.16.1 ; python_version >= "3.9" # for azure content safety azure-keyvault==4.2.0 # for azure KMS integration @@ -50,10 +50,10 @@ azure-storage-file-datalake==12.20.0 # for azure buck storage logging opentelemetry-api==1.28.0 opentelemetry-sdk==1.28.0 opentelemetry-exporter-otlp==1.28.0 -a2a-sdk>=0.3.22 ; python_version >= "3.10" -# grpcio: 1.68.0-1.68.1 has reconnect bug (#38290), 1.75+ has Python 3.14 wheels + fix -grpcio>=1.62.3,!=1.68.*,!=1.69.*,!=1.70.*,!=1.71.0,!=1.71.1,!=1.72.0,!=1.72.1,!=1.73.0; python_version < "3.14" -grpcio>=1.75.0; python_version >= "3.14" +a2a-sdk==0.3.25 ; python_version >= "3.10" +# grpcio: pinned to 1.80.0 (past reconnect bug #38290 in 1.68.x, has Python 3.14 wheels) +grpcio==1.80.0; python_version < "3.14" +grpcio==1.80.0; python_version >= "3.14" sentry_sdk==2.21.0 # for sentry error handling detect-secrets==1.5.0 # Enterprise - secret detection / masking in LLM requests tzdata==2025.1 # IANA time zone database @@ -67,15 +67,22 @@ tokenizers==0.20.2 # for calculating usage click==8.1.7 # for proxy cli rich==13.7.1 # for litellm proxy cli jinja2==3.1.6 # for prompt templates -aioboto3==15.5.0 # for async sagemaker calls (updated to match boto3 1.40.73) +aioboto3==15.5.0 # for async sagemaker calls aiohttp==3.13.3 # for network calls tenacity==8.5.0 # for retrying requests, when litellm.num_retries set -pydantic>=2.11,<3 # proxy + openai req. + mcp -jsonschema>=4.23.0,<5.0.0 # validating json schema - aligned with openapi-core + mcp +pydantic==2.12.5 # proxy + openai req. + mcp +jsonschema==4.26.0 # validating json schema - aligned with openapi-core + mcp websockets==15.0.1 # for realtime API soundfile==0.12.1 # for audio file processing openapi-core==0.21.0 # for OpenAPI compliance tests -pypdf>=6.7.3 # for PDF text extraction in RAG ingestion (CVE-2026-27888) +pypdf==6.9.2 # for PDF text extraction in RAG ingestion (CVE-2026-27888) + +# Transitive deps pinned to prevent floating between builds +aiofiles==24.1.0 # transitive dep (langfuse) +colorlog==6.10.1 # transitive dep (ddtrace) +grpc-google-iam-v1==0.14.3 # transitive dep (google-cloud-iam) +hf-xet==1.4.2 # transitive dep (huggingface_hub) +requests-toolbelt==1.0.0 # transitive dep (langfuse) ######################## # LITELLM ENTERPRISE DEPENDENCIES diff --git a/scripts/health_check/health_check_requirements.txt b/scripts/health_check/health_check_requirements.txt index c9d2650c88..4aba4d49ed 100644 --- a/scripts/health_check/health_check_requirements.txt +++ b/scripts/health_check/health_check_requirements.txt @@ -1,2 +1,2 @@ -httpx>=0.24.0 -pyyaml>=6.0 +httpx==0.28.1 +pyyaml==6.0.2