Skip to content

Fix model-engine image vulnerabilities#854

Open
scale-ballen wants to merge 2 commits into
mainfrom
sec/model-engine-current-cves
Open

Fix model-engine image vulnerabilities#854
scale-ballen wants to merge 2 commits into
mainfrom
sec/model-engine-current-cves

Conversation

@scale-ballen

@scale-ballen scale-ballen commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • upgrade the Python dependencies responsible for the current model-engine vulnerability findings
  • replace the source-built kubectl binary with the digest-pinned Chainguard kubectl binary
  • update aws-iam-authenticator from v0.7.15 to v0.7.18
  • add a focused compatibility fixture for aioresponses with aiohttp 3.14

Why

The latest model-engine-internal image inherited 28 Trivy findings from the public model-engine image. The findings came from vulnerable Python packages and Go dependencies embedded in kubectl and aws-iam-authenticator.

Impact

The rebuilt model-engine image reports zero Trivy vulnerability findings while preserving its health endpoint and bundled Kubernetes authentication tools. model-engine-internal can consume the remediated public image after the corresponding models submodule update.

Validation

  • production-parity linux/amd64 Docker build
  • Trivy: 28 findings before, 0 after
  • unit/API tests: 173 passed, 3 skipped
  • health tests: 16 passed
  • runtime FastAPI /health smoke test: 200 OK
  • kubectl version --client smoke test
  • aws-iam-authenticator version smoke test
  • uv pip check: 251 packages compatible
  • git diff --check

Greptile Summary

This PR remediates 28 Trivy vulnerability findings in the model-engine image by upgrading vulnerable Python dependencies and replacing the source-built kubectl binary with a digest-pinned Chainguard image, while also bumping aws-iam-authenticator from v0.7.15 to v0.7.18.

  • Dockerfile: kubectl is now pulled from cgr.dev/chainguard/kubectl at a pinned digest instead of being compiled from source (kubernetes/kubernetes v1.35.4); aws-iam-authenticator is bumped to v0.7.18 and still cross-compiled with GOARCH=${TARGETARCH}.
  • requirements.in / requirements.txt: aiohttp, cryptography, fastapi, starlette (0.x → 1.x), python-multipart, PyJWT, urllib3, idna, and wheel are all updated to versions that resolve the reported CVEs; the lock file gains httpx2, httpcore2, and truststore as new transitive dependencies of starlette 1.3.1, and drops bleach/webencodings in favour of nh3.
  • test_http_forwarder.py: An autouse fixture patches ClientResponse.__init__ to bridge the aioresponses 0.7.9 / aiohttp 3.14 API incompatibility (new required stream_writer parameter).

Confidence Score: 4/5

Safe to merge for linux/amd64 builds; the kubectl digest warrants a quick manifest-list check before enabling arm64 builds.

All changes are targeted vulnerability remediations validated by the author (zero Trivy findings, 173 unit tests passing). The only open question is whether the pinned kubectl digest resolves to a multi-arch manifest list — if it doesn't, future arm64 builds would silently copy the wrong-arch binary. The aioresponses shim is a clean workaround with a minor risk of masking regressions on untested stream_writer attributes, but it is clearly scoped and documented.

model-engine/Dockerfile — verify that the sha256 digest on the kubectl FROM line is an OCI manifest list (multi-arch index) rather than a single-platform manifest before any arm64 build is attempted.

Important Files Changed

Filename Overview
model-engine/Dockerfile Replaces source-built kubectl (v1.35.4 from GitHub) with a digest-pinned Chainguard image, and bumps aws-iam-authenticator from v0.7.15 to v0.7.18; multi-arch correctness depends on the digest resolving to a manifest list rather than a single-platform manifest.
model-engine/requirements.in Bumps aiohttp, cryptography, fastapi, python-multipart, starlette, PyJWT, urllib3, and adds idna and wheel lower-bounds to address CVE findings; changes are straightforward security pin updates.
model-engine/requirements.txt Locked dependency tree regenerated to match requirements.in; notable new transitive dependencies are httpx2, httpcore2, and truststore pulled in by starlette 1.3.1, and bleach/webencodings replaced by nh3.
model-engine/tests/unit/inference/test_http_forwarder.py Adds an autouse fixture that patches ClientResponse.init to supply a mock stream_writer, working around an aioresponses 0.7.9 incompatibility with aiohttp 3.14's new required parameter.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["cgr.dev/chainguard/kubectl:latest@sha256:…\n(AS kubectl stage)"] -->|COPY /usr/bin/kubectl| B["/tmp/runtime-bin/kubectl"]
    C["cgr.dev/chainguard/python:latest-dev\n(AS builder stage)"] --> D["pip install requirements.txt\n(updated deps: aiohttp 3.14.1, fastapi 0.139, starlette 1.3.1…)"]
    C --> E["git clone v0.7.18\naws-iam-authenticator\nGOARCH=${TARGETARCH}"]
    E --> F["/tmp/runtime-bin/aws-iam-authenticator"]
    B --> G["COPY → /usr/local/bin/kubectl"]
    F --> H["COPY → /usr/local/bin/aws-iam-authenticator"]
    D --> I["cgr.dev/chainguard/python:latest\n(final model-engine image)"]
    G --> I
    H --> I
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["cgr.dev/chainguard/kubectl:latest@sha256:…\n(AS kubectl stage)"] -->|COPY /usr/bin/kubectl| B["/tmp/runtime-bin/kubectl"]
    C["cgr.dev/chainguard/python:latest-dev\n(AS builder stage)"] --> D["pip install requirements.txt\n(updated deps: aiohttp 3.14.1, fastapi 0.139, starlette 1.3.1…)"]
    C --> E["git clone v0.7.18\naws-iam-authenticator\nGOARCH=${TARGETARCH}"]
    E --> F["/tmp/runtime-bin/aws-iam-authenticator"]
    B --> G["COPY → /usr/local/bin/kubectl"]
    F --> H["COPY → /usr/local/bin/aws-iam-authenticator"]
    D --> I["cgr.dev/chainguard/python:latest\n(final model-engine image)"]
    G --> I
    H --> I
Loading

Fix All in Cursor Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
model-engine/Dockerfile:3
**kubectl digest may be single-arch, breaking arm64 builds**

The original kubectl build used `KUBE_BUILD_PLATFORMS=linux/${TARGETARCH}` to produce the correct architecture binary. The replacement `COPY --from=kubectl` does not reference `TARGETARCH`, so its correctness depends entirely on whether this digest resolves to a multi-arch manifest list or a single-platform (amd64) manifest. If the digest is for the amd64-specific manifest rather than the OCI index, an arm64 buildx invocation will silently copy the wrong-arch binary into the image. The PR description validates only `linux/amd64`, but `ARG TARGETARCH` on line 9 and the cross-compiled aws-iam-authenticator on line 49 indicate multi-arch intent. It is worth verifying with `docker manifest inspect cgr.dev/chainguard/kubectl:latest@sha256:e305bc9ffe65a62c20e3bad506a4c42e2d6d79fbe624cd8dcab13a3687f979a6` that the digest refers to a multi-arch index before arm64 builds are attempted.

### Issue 2 of 2
model-engine/tests/unit/inference/test_http_forwarder.py:36-46
**Compatibility shim should track an upstream fix**

The `autouse=True` fixture patches `ClientResponse.__init__` to inject a `mock.Mock(output_size=0)` for the new `stream_writer` parameter introduced in aiohttp 3.14, working around the incompatibility with aioresponses 0.7.9. This is a reasonable short-term shim, but `output_size=0` only satisfies accesses to that one attribute; any test that exercises code paths reading other attributes of `stream_writer` will get an opaque `Mock` return rather than a failure, potentially masking regressions. It would be helpful to file an issue against the `aioresponses` repo tracking the 3.14 incompatibility and add a comment here linking to it so the shim can be cleaned up once aioresponses ships a fix.

Reviews (1): Last reviewed commit: "Merge branch 'main' into sec/model-engin..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

@socket-security

socket-security Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedpypi/​wheel@​0.46.2 ⏵ 0.47.099 +1100100100100
Addedpypi/​httpcore2@​2.3.0100100100100100
Updatedpypi/​fastapi@​0.135.1 ⏵ 0.139.0100 +1100100100100
Addedpypi/​httpx2@​2.3.0100100100100100

View full report

@scale-ballen scale-ballen marked this pull request as ready for review July 14, 2026 14:47
Comment thread model-engine/Dockerfile
@@ -1,5 +1,7 @@
# syntax = docker/dockerfile:1

FROM cgr.dev/chainguard/kubectl:latest@sha256:e305bc9ffe65a62c20e3bad506a4c42e2d6d79fbe624cd8dcab13a3687f979a6 AS kubectl

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 kubectl digest may be single-arch, breaking arm64 builds

The original kubectl build used KUBE_BUILD_PLATFORMS=linux/${TARGETARCH} to produce the correct architecture binary. The replacement COPY --from=kubectl does not reference TARGETARCH, so its correctness depends entirely on whether this digest resolves to a multi-arch manifest list or a single-platform (amd64) manifest. If the digest is for the amd64-specific manifest rather than the OCI index, an arm64 buildx invocation will silently copy the wrong-arch binary into the image. The PR description validates only linux/amd64, but ARG TARGETARCH on line 9 and the cross-compiled aws-iam-authenticator on line 49 indicate multi-arch intent. It is worth verifying with docker manifest inspect cgr.dev/chainguard/kubectl:latest@sha256:e305bc9ffe65a62c20e3bad506a4c42e2d6d79fbe624cd8dcab13a3687f979a6 that the digest refers to a multi-arch index before arm64 builds are attempted.

Prompt To Fix With AI
This is a comment left during a code review.
Path: model-engine/Dockerfile
Line: 3

Comment:
**kubectl digest may be single-arch, breaking arm64 builds**

The original kubectl build used `KUBE_BUILD_PLATFORMS=linux/${TARGETARCH}` to produce the correct architecture binary. The replacement `COPY --from=kubectl` does not reference `TARGETARCH`, so its correctness depends entirely on whether this digest resolves to a multi-arch manifest list or a single-platform (amd64) manifest. If the digest is for the amd64-specific manifest rather than the OCI index, an arm64 buildx invocation will silently copy the wrong-arch binary into the image. The PR description validates only `linux/amd64`, but `ARG TARGETARCH` on line 9 and the cross-compiled aws-iam-authenticator on line 49 indicate multi-arch intent. It is worth verifying with `docker manifest inspect cgr.dev/chainguard/kubectl:latest@sha256:e305bc9ffe65a62c20e3bad506a4c42e2d6d79fbe624cd8dcab13a3687f979a6` that the digest refers to a multi-arch index before arm64 builds are attempted.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Cursor Fix in Claude Code Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant