Skip to content

Commit 8781b44

Browse files
authored
fix: strip base image's system pip/setuptools tripping image-scan (#120)
image-scan has been red since 2026-08-04. Trivy flagged HIGH findings (msgpack GHSA-6v7p-g79w-8964, setuptools CVE-2025-47273) that contradict uv.lock, which already pins the fixed versions (msgpack 1.2.1, setuptools 82.0.1). Confirmed H2, not H1: direct inspection of the built image showed no scan-ref/SBOM misconfiguration in the workflow (Trivy already scans image-ref, not a workspace SBOM). Instead python:3.14-slim ships its own system pip whose pip/_vendor/msgpack is a separate vendored copy, plus a bundled wheel under ensurepip/_bundled/ -- both pip-installed, so `apt-get upgrade` never touches them. The app only runs from the isolated /app/.venv populated from uv.lock, which never contained either package. The runtime stage now removes the base image's ensurepip module, system pip/setuptools/pkg_resources, and their /usr/local/bin shims -- dead weight with no runtime purpose. A third, real finding also surfaced during the discriminating scan: aiohttp 3.14.1 (transitive via langchain-community) has a fixed HIGH CVE (CVE-2026-69244) in the actual locked venv. Bumped via `uv lock --upgrade-package aiohttp` (3.14.1 -> 3.14.3), touching only that package in uv.lock. Verified: docker build + trivy image --exit-code 1 --ignore-unfixed --severity HIGH,CRITICAL now reports zero findings; container still starts and passes its /health check.
1 parent 79d26ff commit 8781b44

3 files changed

Lines changed: 115 additions & 85 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
- **`image-scan` red since 2026-08-04, blocking every PR** — Trivy flagged HIGH findings (`GHSA-6v7p-g79w-8964` in `msgpack` 1.1.2, `CVE-2025-47273` in `setuptools` 70.3.0) that contradicted `uv.lock`, which already pins the fixed `msgpack` 1.2.1 and `setuptools` 82.0.1. Confirmed via direct filesystem inspection of the built image (H2 from the investigation, not H1): the vulnerable copies were the base image's *own* system-Python packaging tools — `python:3.14-slim` ships a system `pip` whose `pip/_vendor/msgpack` is a separate vendored copy, plus a bundled wheel under `ensurepip/_bundled/`, both pip-installed and therefore invisible to `apt-get upgrade`. The application only ever runs from the isolated `/app/.venv` populated from `uv.lock`, which never contained either vulnerable package. `infra/Dockerfile`'s runtime stage now strips the base image's `ensurepip`, system `pip`/`setuptools`/`pkg_resources`, and their `/usr/local/bin` shims — dead weight with no runtime purpose, since the app never invokes the system interpreter's pip. A genuine third finding surfaced during the same scan that the base-image theory does *not* explain — `aiohttp` 3.14.1 (pulled in transitively by `langchain-community`) has a real fixed HIGH CVE (`CVE-2026-69244`) in the actual locked venv; `uv lock --upgrade-package aiohttp` bumped it to 3.14.3 with no other lockfile changes. Verified: `docker build` + `trivy image --exit-code 1 --ignore-unfixed --severity HIGH,CRITICAL` now reports zero findings, and the container still starts and passes its `/health` check.
12+
1013
## [0.7.0] - 2026-07-16
1114

1215
### Added

infra/Dockerfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,33 @@ RUN apt-get update \
6464
&& apt-get upgrade -y --no-install-recommends \
6565
&& rm -rf /var/lib/apt/lists/*
6666

67+
# Strip the base image's own pip/setuptools instead of patching them.
68+
#
69+
# python:3.14-slim ships pip (and, on some base image builds, setuptools) as
70+
# pip-installed packages under the system interpreter's site-packages, plus
71+
# a bundled pip wheel under ensurepip/_bundled/. Those are *not* dpkg-managed,
72+
# so `apt-get upgrade` above never touches them — and pip vendors its own
73+
# copy of third-party libraries (e.g. msgpack) inside pip/_vendor/, which can
74+
# lag behind the fixed version on PyPI even when the base image is otherwise
75+
# current. This is exactly what tripped image-scan on 2026-08-04: Trivy
76+
# flagged HIGH/CRITICAL CVEs (GHSA-6v7p-g79w-8964 in vendored msgpack,
77+
# CVE-2025-47273 in setuptools) that uv.lock already carries fixed versions
78+
# of — the vulnerable copies were these base-image system packages, not the
79+
# application's dependencies.
80+
#
81+
# The application only ever runs from the isolated venv copied in below
82+
# (VIRTUAL_ENV=/app/.venv), which uv populated from uv.lock and never touches
83+
# system site-packages, so removing the base image's own packaging tools is
84+
# safe and has no runtime effect. If a future base image bump reintroduces a
85+
# vulnerable pip/setuptools here, re-run/extend this step — don't reach for
86+
# apt-get, it cannot see this layer.
87+
RUN find /usr/local/lib/python3.* -maxdepth 1 -type d -name ensurepip -exec rm -rf {} + \
88+
&& find /usr/local/lib/python3.*/site-packages -maxdepth 1 \
89+
\( -iname 'pip' -o -iname 'pip-*.dist-info' -o -iname 'setuptools' \
90+
-o -iname 'setuptools-*.dist-info' -o -iname 'pkg_resources' \) \
91+
-exec rm -rf {} + \
92+
&& rm -f /usr/local/bin/pip /usr/local/bin/pip3 /usr/local/bin/pip3.*
93+
6794
# Create a non-root user and group
6895
RUN groupadd --gid 1001 appgroup \
6996
&& useradd --uid 1001 --gid appgroup --shell /sbin/nologin --no-create-home appuser

0 commit comments

Comments
 (0)