Run the scan gate; harden the image and stop short of release
glas-harness asked for a scanned immutable image. The scan ran, and it failed
on the base we had sanctioned, so no image was pushed.
Every finding is inherited from the base image or its distro packages; none is
in approval_engine code. Two fixes applied here:
The base pin was stale. It named a Debian 13.5 build of python:3.12-slim while
upstream is 13.6. Bumping the digest removes 30 HIGH and 47 MEDIUM on its own.
Still a digest, not a floating tag.
pip is gone from the runtime image. All 10 MEDIUM Python findings were in pip
itself, a build-time tool with no business in a running approval service. The
build is now two-stage, and pip is removed from both the venv and the base's
/usr/local, so command -v pip returns nothing.
What remains is a decision rather than a task. Three CRITICALs persist on
Debian, all perl-base (CVE-2026-13221, CVE-2026-42496, CVE-2026-8376), none
with an upstream fix, in a package this service never invokes and that Debian
marks Essential. An Alpine variant carries no perl and scans 0 CRITICAL / 7
HIGH / 1 MEDIUM against Debian's 3 / 51 / 56.
Alpine is proven viable rather than asserted: musl wheels resolve with no
toolchain, the full suite passes on musl at 111 tests, and non-root uid 10001,
schema v3, tenant:platform, fresh-store migrate/verify and both production
fail-closed gates all hold in the built image. It is parked in
Containerfile.alpine as a candidate; Containerfile remains sanctioned.
Nothing was released. Pushing the Debian variant would pin three unfixable
CRITICALs into a release digest, and choosing the runtime C library for this
service is not a call to make silently. The manifest still carries
REPLACE_WITH_RELEASE_DIGEST. Full record in docs/image-scan-2026-09-06.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-06 22:52:20 +02:00
|
|
|
# Build stage: pip exists here and is never copied into the runtime image.
|
|
|
|
|
FROM python:3.12-slim@sha256:78387bc3881b8273120a12ebe6c1ab22b018ccc2c9adf565ae1ac9b536e184ea AS build
|
2026-09-02 00:52:04 +02:00
|
|
|
|
|
|
|
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
|
|
|
PYTHONUNBUFFERED=1 \
|
|
|
|
|
PATH=/opt/venv/bin:$PATH
|
|
|
|
|
|
Run the scan gate; harden the image and stop short of release
glas-harness asked for a scanned immutable image. The scan ran, and it failed
on the base we had sanctioned, so no image was pushed.
Every finding is inherited from the base image or its distro packages; none is
in approval_engine code. Two fixes applied here:
The base pin was stale. It named a Debian 13.5 build of python:3.12-slim while
upstream is 13.6. Bumping the digest removes 30 HIGH and 47 MEDIUM on its own.
Still a digest, not a floating tag.
pip is gone from the runtime image. All 10 MEDIUM Python findings were in pip
itself, a build-time tool with no business in a running approval service. The
build is now two-stage, and pip is removed from both the venv and the base's
/usr/local, so command -v pip returns nothing.
What remains is a decision rather than a task. Three CRITICALs persist on
Debian, all perl-base (CVE-2026-13221, CVE-2026-42496, CVE-2026-8376), none
with an upstream fix, in a package this service never invokes and that Debian
marks Essential. An Alpine variant carries no perl and scans 0 CRITICAL / 7
HIGH / 1 MEDIUM against Debian's 3 / 51 / 56.
Alpine is proven viable rather than asserted: musl wheels resolve with no
toolchain, the full suite passes on musl at 111 tests, and non-root uid 10001,
schema v3, tenant:platform, fresh-store migrate/verify and both production
fail-closed gates all hold in the built image. It is parked in
Containerfile.alpine as a candidate; Containerfile remains sanctioned.
Nothing was released. Pushing the Debian variant would pin three unfixable
CRITICALs into a release digest, and choosing the runtime C library for this
service is not a call to make silently. The manifest still carries
REPLACE_WITH_RELEASE_DIGEST. Full record in docs/image-scan-2026-09-06.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-06 22:52:20 +02:00
|
|
|
RUN python -m venv /opt/venv
|
2026-09-02 00:52:04 +02:00
|
|
|
|
|
|
|
|
WORKDIR /app
|
|
|
|
|
COPY pyproject.toml README.md ./
|
|
|
|
|
COPY approval_engine ./approval_engine
|
Run the scan gate; harden the image and stop short of release
glas-harness asked for a scanned immutable image. The scan ran, and it failed
on the base we had sanctioned, so no image was pushed.
Every finding is inherited from the base image or its distro packages; none is
in approval_engine code. Two fixes applied here:
The base pin was stale. It named a Debian 13.5 build of python:3.12-slim while
upstream is 13.6. Bumping the digest removes 30 HIGH and 47 MEDIUM on its own.
Still a digest, not a floating tag.
pip is gone from the runtime image. All 10 MEDIUM Python findings were in pip
itself, a build-time tool with no business in a running approval service. The
build is now two-stage, and pip is removed from both the venv and the base's
/usr/local, so command -v pip returns nothing.
What remains is a decision rather than a task. Three CRITICALs persist on
Debian, all perl-base (CVE-2026-13221, CVE-2026-42496, CVE-2026-8376), none
with an upstream fix, in a package this service never invokes and that Debian
marks Essential. An Alpine variant carries no perl and scans 0 CRITICAL / 7
HIGH / 1 MEDIUM against Debian's 3 / 51 / 56.
Alpine is proven viable rather than asserted: musl wheels resolve with no
toolchain, the full suite passes on musl at 111 tests, and non-root uid 10001,
schema v3, tenant:platform, fresh-store migrate/verify and both production
fail-closed gates all hold in the built image. It is parked in
Containerfile.alpine as a candidate; Containerfile remains sanctioned.
Nothing was released. Pushing the Debian variant would pin three unfixable
CRITICALs into a release digest, and choosing the runtime C library for this
service is not a call to make silently. The manifest still carries
REPLACE_WITH_RELEASE_DIGEST. Full record in docs/image-scan-2026-09-06.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-06 22:52:20 +02:00
|
|
|
RUN pip install --no-cache-dir '.[serve]' \
|
|
|
|
|
&& pip uninstall -y pip setuptools wheel 2>/dev/null || true \
|
|
|
|
|
&& rm -rf /opt/venv/bin/pip /opt/venv/bin/pip3 /opt/venv/bin/pip3.12 \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/pip \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/pip-*.dist-info \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/setuptools \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/setuptools-*.dist-info \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/pkg_resources \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/wheel \
|
|
|
|
|
/opt/venv/lib/python3.12/site-packages/wheel-*.dist-info
|
2026-09-02 00:52:04 +02:00
|
|
|
|
Run the scan gate; harden the image and stop short of release
glas-harness asked for a scanned immutable image. The scan ran, and it failed
on the base we had sanctioned, so no image was pushed.
Every finding is inherited from the base image or its distro packages; none is
in approval_engine code. Two fixes applied here:
The base pin was stale. It named a Debian 13.5 build of python:3.12-slim while
upstream is 13.6. Bumping the digest removes 30 HIGH and 47 MEDIUM on its own.
Still a digest, not a floating tag.
pip is gone from the runtime image. All 10 MEDIUM Python findings were in pip
itself, a build-time tool with no business in a running approval service. The
build is now two-stage, and pip is removed from both the venv and the base's
/usr/local, so command -v pip returns nothing.
What remains is a decision rather than a task. Three CRITICALs persist on
Debian, all perl-base (CVE-2026-13221, CVE-2026-42496, CVE-2026-8376), none
with an upstream fix, in a package this service never invokes and that Debian
marks Essential. An Alpine variant carries no perl and scans 0 CRITICAL / 7
HIGH / 1 MEDIUM against Debian's 3 / 51 / 56.
Alpine is proven viable rather than asserted: musl wheels resolve with no
toolchain, the full suite passes on musl at 111 tests, and non-root uid 10001,
schema v3, tenant:platform, fresh-store migrate/verify and both production
fail-closed gates all hold in the built image. It is parked in
Containerfile.alpine as a candidate; Containerfile remains sanctioned.
Nothing was released. Pushing the Debian variant would pin three unfixable
CRITICALs into a release digest, and choosing the runtime C library for this
service is not a call to make silently. The manifest still carries
REPLACE_WITH_RELEASE_DIGEST. Full record in docs/image-scan-2026-09-06.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-06 22:52:20 +02:00
|
|
|
# Runtime stage.
|
|
|
|
|
FROM python:3.12-slim@sha256:78387bc3881b8273120a12ebe6c1ab22b018ccc2c9adf565ae1ac9b536e184ea
|
|
|
|
|
|
|
|
|
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
|
|
|
PYTHONUNBUFFERED=1 \
|
|
|
|
|
PATH=/opt/venv/bin:$PATH
|
|
|
|
|
|
|
|
|
|
RUN addgroup --system --gid 10001 approval \
|
|
|
|
|
&& adduser --system --uid 10001 --ingroup approval --no-create-home approval \
|
|
|
|
|
&& python -m pip uninstall -y pip setuptools wheel 2>/dev/null || true \
|
|
|
|
|
&& rm -rf /usr/local/bin/pip /usr/local/bin/pip3 /usr/local/bin/pip3.12 \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/pip \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/pip-*.dist-info \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/setuptools \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/setuptools-*.dist-info \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/pkg_resources \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/wheel \
|
|
|
|
|
/usr/local/lib/python3.12/site-packages/wheel-*.dist-info
|
|
|
|
|
|
|
|
|
|
COPY --from=build /opt/venv /opt/venv
|
|
|
|
|
|
|
|
|
|
WORKDIR /app
|
2026-09-02 00:52:04 +02:00
|
|
|
USER 10001:10001
|
|
|
|
|
EXPOSE 8080
|
|
|
|
|
ENTRYPOINT ["approval-engine"]
|
|
|
|
|
CMD ["serve", "--help"]
|