diff --git a/backend/Dockerfile b/backend/Dockerfile index e89058db..688820ed 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -27,8 +27,15 @@ FROM node:22-alpine WORKDIR /app +# Redeclare CACHEBUST — ARGs don't cross stage boundaries, so the builder +# stage's declaration never reached this stage. Consuming it in the RUN below +# busts that layer's cache every CI run (CACHEBUST=github.run_number), so the +# image always picks up current Alpine security updates instead of reusing a +# stale cached upgrade layer. +ARG CACHEBUST=1 + # Upgrade all packages to fix security vulnerabilities (OpenSSL, libexpat, BusyBox CVEs) -RUN apk upgrade --no-cache +RUN echo "cachebust=${CACHEBUST}" && apk upgrade --no-cache # Upgrade the npm CLI in the final image so its bundled deps are patched # (sigstore 4.x, tar) — closes CVE-2026-48815 and the older @sigstore/core / tar diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 586e4754..eed1130d 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -29,14 +29,24 @@ COPY . . # Build the application RUN npm run build -# Production stage (Alpine 3.23 with OpenSSL 3.5.5, patched libexpat) -FROM nginx:1.28-alpine +# Production stage (nginx stable 1.30 on Alpine 3.24). The 1.28 base is a +# dead end for the nginx HTTP/2 + rewrite/charset CVEs (CVE-2026-42055 / +# -49975 / -9256 / -48142): nginx.org's nginx-module-* packages pin the exact +# nginx version, so `apk upgrade` can never pull Alpine's patched 1.28.3-r4 — +# nginx fixes have to come via the base image tag, not apk. +FROM nginx:1.30-alpine -# Upgrade all Alpine packages for security fixes. The explicit nginx upgrade -# closes the HTTP/2 + rewrite/charset CVEs (CVE-2026-42055 / -49975 / -9256 / -# -48142, fixed in nginx 1.28.3-r4) and busts any cached layer still carrying -# the vulnerable r1 build. -RUN apk upgrade --no-cache && apk add --no-cache --upgrade nginx +# Redeclare CACHEBUST — ARGs don't cross stage boundaries, so the builder +# stage's declaration never reached this stage. Consuming it in the RUN below +# busts that layer's cache every CI run (CACHEBUST=github.run_number), so the +# image always picks up current Alpine security updates. Without this, the +# upgrade layer was cached indefinitely and builds kept shipping curl 8.19.0 / +# c-ares 1.34.6 for weeks after fixed packages landed in the Alpine repo. +ARG CACHEBUST=1 + +# Upgrade all Alpine packages for security fixes (nginx itself is version- +# pinned by its module packages — see the FROM comment above). +RUN echo "cachebust=${CACHEBUST}" && apk upgrade --no-cache # Install runtime dependencies. `gettext` provides envsubst, used by # docker-entrypoint.sh for the BRAND_TITLE / BRAND_DESCRIPTION runtime