From 609cc5ecfb8034b3ce376b1e26fb44e6084d9be6 Mon Sep 17 00:00:00 2001 From: Brandon Allen Date: Tue, 14 Jul 2026 10:32:59 -0400 Subject: [PATCH] fix model-engine image vulnerabilities --- model-engine/Dockerfile | 10 ++-- model-engine/requirements.in | 18 ++++--- model-engine/requirements.txt | 49 +++++++++++-------- .../unit/inference/test_http_forwarder.py | 14 ++++++ 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/model-engine/Dockerfile b/model-engine/Dockerfile index f8363e604..47250943d 100644 --- a/model-engine/Dockerfile +++ b/model-engine/Dockerfile @@ -1,5 +1,7 @@ # syntax = docker/dockerfile:1 +FROM cgr.dev/chainguard/kubectl:latest@sha256:e305bc9ffe65a62c20e3bad506a4c42e2d6d79fbe624cd8dcab13a3687f979a6 AS kubectl + FROM cgr.dev/chainguard/python:latest-dev AS builder USER root @@ -42,14 +44,12 @@ RUN mkdir -p /tmp/runtime-bin /tmp/runtime-libs && \ cp /usr/lib/libreadline.so.8* /tmp/runtime-libs/ && \ cp /usr/lib/libtinfo.so.6* /tmp/runtime-libs/ && \ cp /usr/lib/libz.so.1* /tmp/runtime-libs/ && \ - git clone --depth 1 --branch v1.35.4 https://github.com/kubernetes/kubernetes.git /tmp/k8s && \ - cd /tmp/k8s && \ - GOTOOLCHAIN=local KUBE_BUILD_PLATFORMS=linux/${TARGETARCH} make WHAT=cmd/kubectl && \ - cp _output/local/bin/linux/${TARGETARCH}/kubectl /tmp/runtime-bin/kubectl && \ - git clone --depth 1 --branch v0.7.15 https://github.com/kubernetes-sigs/aws-iam-authenticator.git /tmp/aws-iam-authenticator && \ + git clone --depth 1 --branch v0.7.18 https://github.com/kubernetes-sigs/aws-iam-authenticator.git /tmp/aws-iam-authenticator && \ cd /tmp/aws-iam-authenticator && \ GOOS=linux GOARCH=${TARGETARCH} go build -o /tmp/runtime-bin/aws-iam-authenticator ./cmd/aws-iam-authenticator +COPY --from=kubectl /usr/bin/kubectl /tmp/runtime-bin/kubectl + FROM cgr.dev/chainguard/python:latest AS model-engine USER root diff --git a/model-engine/requirements.in b/model-engine/requirements.in index c1939905c..7da000eea 100644 --- a/model-engine/requirements.in +++ b/model-engine/requirements.in @@ -1,6 +1,6 @@ GitPython>=3.1.49,<4.0 Jinja2>=3.1.5 # CVE-2024-56326; 3.1.0 bug was fixed in 3.1.1+ -aiohttp>=3.13.4,<4.0 +aiohttp>=3.14.1,<4.0 # CVE-2026-34993, CVE-2026-47265, CVE-2026-50269, CVE-2026-54273-54280 redis>=4.6.0 # replaces aioredis~=2.0; aioredis 2.x broken on Python 3.12 (duplicate base class TimeoutError); asyncio support built-in to redis>=4.2 alembic==1.8.1 asyncpg>=0.29.0 # 0.27.0 has no cp312/cp313 wheel; Python 3.12/3.13 support added in 0.29.0 @@ -31,7 +31,7 @@ gevent>=26.5.0 # celery gevent worker pool for the celery-forwarder (MLI-7328); click~=8.1 cloudpickle==2.1.0 croniter==1.4.1 -cryptography>=46.0.7 # not used directly, but needs to be pinned for Microsoft security scan +cryptography>=48.0.1 # GHSA-537c-gmf6-5ccf fixed in 48.0.1 dataclasses-json>=0.5.7 datadog-api-client==2.11.0 datadog~=0.47.0 @@ -39,7 +39,7 @@ ddtrace>=4.7.1,<5.0 # 4.7.1 publishes CPython 3.14 wheels; needed for public Ch numpy>=2.4.4,<2.5 # 2.4.4 publishes CPython 3.14 wheels deprecation~=2.1 docker~=5.0 -fastapi>=0.115.8 # bumped to allow starlette>=0.49.1 (CVE-2025-62727 fix) +fastapi>=0.138.0 # compatible with starlette>=1.3.1 security fixes gitdb2~=2.0 gunicorn~=23.0 httptools>=0.6.0 # 0.5.0 has no cp312/cp313 wheel @@ -54,7 +54,7 @@ py-xid==0.3.0 pycurl~=7.44 # For celery[sqs] pytz>=2024.1 pydantic==2.12.5 -python-multipart>=0.0.26 +python-multipart>=0.0.30 # CVE-2026-53539 fixed in 0.0.30 quart>=0.20.0,<0.21.0 werkzeug>=3.0.6 # CVE-2024-34069, CVE-2024-49766, CVE-2024-49767 requests-auth-aws-sigv4~=0.7 @@ -66,7 +66,7 @@ smart-open~=5.2 sqlalchemy[asyncio]>=2.0.36 # 2.0.36+ required for Python 3.13 (__static_attributes__ / __firstlineno__ compat) sse-starlette==1.6.1 sseclient-py==1.7.2 -starlette[full]>=0.40.0 # not used directly, but needs to be pinned for Microsoft security scan +starlette[full]>=1.3.1 # CVE-2026-48818 and CVE-2026-54283 fixed by 1.3.1 stringcase==1.2.0 tenacity>=6.0.0,<=6.2.0 testing-postgresql==1.3.0 @@ -78,16 +78,18 @@ uvicorn==0.30.6 uvloop>=0.19.0 # 0.17.0 has no cp312/cp313 wheel; Python 3.12/3.13 support added in 0.19.0 yarl~=1.4 certifi>=2024.7.4 # CVE-2024-39689 -PyJWT>=2.9.0 # CVE-2024-33663 -urllib3>=2.0.7 # CVE-2023-43804, CVE-2023-45803, CVE-2024-37891 +PyJWT>=2.13.0 # CVE-2024-33663 and CVE-2026-48526 +urllib3>=2.7.0 # CVE-2026-44431 and CVE-2026-44432 +idna>=3.15 # CVE-2026-45409 setuptools>=70.0.0 # CVE-2024-6345 +wheel>=0.46.2 # CVE-2026-24049 (GHSA-8rrh-rw8j-w5fx) h11>=0.16.0 # CVE-2025-43859 (CRITICAL) greenlet>=3.0.0 # 2.x has no cp312/cp313 wheel; Python 3.12/3.13 support added in 3.0 frozenlist>=1.4.0 # 1.3.x has no cp312/cp313 wheel multidict>=6.1.0 # 6.0.x has no cp312/cp313 wheel azure-core>=1.38.0 # CVE-2026-21226 (HIGH, deserialization) fixed in 1.38.0 pyasn1>=0.6.3 # CVE-2026-30922 (HIGH, DoS) fixed in 0.6.3 -starlette>=0.49.1 # CVE-2025-62727 (HIGH, DoS) fixed in 0.49.1 +starlette>=1.3.1 # CVE-2025-62727, CVE-2026-48818, CVE-2026-54283 pg8000>=1.31.5 # CVE-2025-61385 (HIGH, SQL injection) fixed in 1.31.5 flask>=3.1.3,<4.0 # CVE-2026-27205 mako>=1.3.11 # GHSA-v92g-xgxw-vvmm diff --git a/model-engine/requirements.txt b/model-engine/requirements.txt index 32e1fdecd..6c2ad25fb 100644 --- a/model-engine/requirements.txt +++ b/model-engine/requirements.txt @@ -11,7 +11,7 @@ aiofiles==25.1.0 # quart aiohappyeyeballs==2.6.1 # via aiohttp -aiohttp==3.13.5 +aiohttp==3.14.1 # via # -r requirements.in # aiobotocore @@ -34,6 +34,7 @@ annotated-types==0.7.0 anyio==3.7.1 # via # httpx + # httpx2 # starlette asn1crypto==1.5.1 # via scramp @@ -65,8 +66,6 @@ backoff==2.2.1 # via gcloud-aio-auth billiard==4.2.4 # via celery -bleach==6.0.0 - # via readme-renderer blinker==1.9.0 # via # flask @@ -135,7 +134,7 @@ commonmark==0.9.1 # via rich croniter==1.4.1 # via -r requirements.in -cryptography==47.0.0 +cryptography==48.0.1 # via # -r requirements.in # azure-identity @@ -155,11 +154,11 @@ deprecation==2.1.0 # via -r requirements.in docker==5.0.3 # via -r requirements.in -docutils==0.20.1 +docutils==0.23 # via readme-renderer envier==0.6.1 # via ddtrace -fastapi==0.135.1 +fastapi==0.139.0 # via -r requirements.in filelock==3.29.0 # via @@ -180,6 +179,8 @@ gcloud-aio-auth==5.4.4 # via gcloud-aio-storage gcloud-aio-storage==9.6.1 # via -r requirements.in +gevent==26.5.0 + # via -r requirements.in gitdb==4.0.10 # via gitpython gitdb2==2.0.6 @@ -225,8 +226,6 @@ googleapis-common-protos==1.72.0 # grpc-google-iam-v1 # grpcio-status # opentelemetry-exporter-otlp-proto-grpc -gevent==26.5.0 - # via -r requirements.in greenlet==3.3.2 # via # -r requirements.in @@ -256,6 +255,7 @@ h11==0.16.0 # via # -r requirements.in # httpcore + # httpcore2 # hypercorn # uvicorn # wsproto @@ -269,12 +269,16 @@ hpack==4.1.0 # via h2 httpcore==1.0.9 # via httpx +httpcore2==2.3.0 + # via httpx2 httptools==0.7.1 # via -r requirements.in httpx==0.27.0 # via # huggingface-hub # starlette +httpx2==2.3.0 + # via starlette huggingface-hub==1.13.0 # via # tokenizers @@ -283,10 +287,12 @@ hypercorn==0.14.4 # via quart hyperframe==6.1.0 # via h2 -idna==3.7 +idna==3.18 # via + # -r requirements.in # anyio # httpx + # httpx2 # requests # yarl importlib-metadata==6.8.0 @@ -329,8 +335,6 @@ kubernetes==25.3.0 # via -r requirements.in kubernetes-asyncio==25.11.0 # via -r requirements.in -legacy-cgi==2.6.4 - # via ddtrace mako==1.3.12 # via # -r requirements.in @@ -379,6 +383,8 @@ mypy-boto3-sqs==1.40.61 # via boto3-stubs mypy-extensions==1.0.0 # via typing-inspect +nh3==0.3.6 + # via readme-renderer numpy==2.4.4 # via # -r requirements.in @@ -478,7 +484,7 @@ pygments==2.20.0 # -r requirements.in # readme-renderer # rich -pyjwt==2.12.1 +pyjwt==2.13.0 # via # -r requirements.in # gcloud-aio-auth @@ -495,7 +501,7 @@ python-dateutil==2.8.2 # kubernetes # kubernetes-asyncio # pg8000 -python-multipart==0.0.27 +python-multipart==0.0.32 # via # -r requirements.in # starlette @@ -511,7 +517,7 @@ pyyaml==6.0.1 # transformers quart==0.20.0 # via -r requirements.in -readme-renderer==40.0 +readme-renderer==45.0 # via twine redis==4.6.0 # via @@ -562,15 +568,12 @@ setuptools==82.0.1 # -r requirements.in # kubernetes # kubernetes-asyncio -wheel==0.46.2 - # via -r requirements.in # CVE-2026-24049 (GHSA-8rrh-rw8j-w5fx); patched in 0.46.2 sh==1.14.3 # via -r requirements.in shellingham==1.5.4 # via typer six==1.16.0 # via - # bleach # isodate # kubernetes # kubernetes-asyncio @@ -596,7 +599,7 @@ sse-starlette==1.6.1 # via -r requirements.in sseclient-py==1.7.2 # via -r requirements.in -starlette==0.52.1 +starlette==1.3.1 # via # -r requirements.in # fastapi @@ -623,6 +626,10 @@ tqdm==4.67.3 # twine transformers==5.7.0 # via -r requirements.in +truststore==0.10.4 + # via + # httpcore2 + # httpx2 twine==3.7.1 # via -r requirements.in typer==0.23.1 @@ -663,7 +670,7 @@ typing-inspection==0.4.2 # pydantic tzdata==2025.3 # via kombu -urllib3==2.6.3 +urllib3==2.7.0 # via # -r requirements.in # botocore @@ -684,8 +691,6 @@ vine==5.1.0 # kombu wcwidth==0.2.6 # via prompt-toolkit -webencodings==0.5.1 - # via bleach websocket-client==1.6.1 # via # docker @@ -695,6 +700,8 @@ werkzeug==3.1.6 # -r requirements.in # flask # quart +wheel==0.47.0 + # via -r requirements.in wrapt==1.17.3 # via # aiobotocore diff --git a/model-engine/tests/unit/inference/test_http_forwarder.py b/model-engine/tests/unit/inference/test_http_forwarder.py index bb255fea2..00c224f01 100644 --- a/model-engine/tests/unit/inference/test_http_forwarder.py +++ b/model-engine/tests/unit/inference/test_http_forwarder.py @@ -6,6 +6,7 @@ import pytest import requests_mock +from aiohttp import ClientResponse from aioresponses import aioresponses from fastapi import BackgroundTasks, FastAPI from fastapi.responses import JSONResponse @@ -32,6 +33,19 @@ PAYLOAD: Mapping[str, str] = {"hello": "world"} +@pytest.fixture(autouse=True) +def aioresponses_aiohttp_314_compat(monkeypatch): + """Allow aioresponses 0.7.9 to construct aiohttp 3.14 responses.""" + original_init = ClientResponse.__init__ + + def compatible_init(self, *args, stream_writer=None, **kwargs): + if stream_writer is None: + stream_writer = mock.Mock(output_size=0) + original_init(self, *args, stream_writer=stream_writer, **kwargs) + + monkeypatch.setattr(ClientResponse, "__init__", compatible_init) + + class ExceptionCapturedThread(threading.Thread): def __init__(self, target, args): super().__init__(target=target, args=args)