From 22e53fafd5960707feff1e581eb7b3624626da4a Mon Sep 17 00:00:00 2001 From: Lucas Bedatty <79675696+bedatty@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:32:20 -0300 Subject: [PATCH 1/3] fix(build): force no-cache so images stop shipping stale ca-certificates The gha cache replays the old apk/apt layer, so a rebuild resolves no packages and the published image keeps the vulnerable ca-certificates. Set no-cache on the three publishing build-push steps. cache-to is kept on purpose: the clean layers are still exported, so the first build after the revert starts from a healthy cache. Temporary - revert once every repo is rebuilt and redeployed (#953). --- .github/workflows/build.yml | 8 ++++++++ src/build/docker-build-ts/action.yml | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5f52563..486843ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -732,6 +732,10 @@ jobs: VERSION=${{ steps.version.outputs.version }} REVISION=${{ steps.source.outputs.sha }} BUILD_TIME=${{ steps.version.outputs.build_time }} + # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps + # the vulnerable ca-certificates. Revert once every repo has been rebuilt and + # redeployed. See issue #953. + no-cache: true cache-from: type=gha cache-to: type=gha,mode=max secrets: | @@ -859,6 +863,10 @@ jobs: BUILD_TIME=${{ steps.version.outputs.build_time }} sbom: generator=docker/scout-sbom-indexer:latest provenance: mode=max + # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps + # the vulnerable ca-certificates. Revert once every repo has been rebuilt and + # redeployed. See issue #953. + no-cache: true cache-from: type=gha cache-to: type=gha,mode=max secrets: | diff --git a/src/build/docker-build-ts/action.yml b/src/build/docker-build-ts/action.yml index 15c67a0a..dd2b8a06 100644 --- a/src/build/docker-build-ts/action.yml +++ b/src/build/docker-build-ts/action.yml @@ -295,6 +295,10 @@ runs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps + # the vulnerable ca-certificates. Revert once every repo has been rebuilt and + # redeployed. See issue #953. + no-cache: true cache-from: type=gha cache-to: type=gha,mode=max secrets: ${{ steps.secrets.outputs.value }} From cd663de665d4207b2cf5c12a1ab1b07dc666162b Mon Sep 17 00:00:00 2001 From: Lucas Bedatty <79675696+bedatty@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:38:47 -0300 Subject: [PATCH 2/3] fix(build): re-resolve the base image so no-cache covers FROM too no-cache re-runs every Dockerfile step, but it does not re-resolve the base image: a ca-certificates that ships inside FROM survives it. On an ephemeral runner the base usually is pulled fresh, which makes the gap incidental rather than guaranteed. Set pull on the same three publishing steps so both paths are closed. Temporary - reverted together with no-cache (#953). --- .github/workflows/build.yml | 12 ++++++++---- src/build/docker-build-ts/action.yml | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 486843ea..934d168a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -733,9 +733,11 @@ jobs: REVISION=${{ steps.source.outputs.sha }} BUILD_TIME=${{ steps.version.outputs.build_time }} # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps - # the vulnerable ca-certificates. Revert once every repo has been rebuilt and - # redeployed. See issue #953. + # the vulnerable ca-certificates. no-cache re-runs every step; pull re-resolves + # FROM, because no-cache alone leaves a base image that carries the bad package + # untouched. Revert once every repo has been rebuilt and redeployed. See #953. no-cache: true + pull: true cache-from: type=gha cache-to: type=gha,mode=max secrets: | @@ -864,9 +866,11 @@ jobs: sbom: generator=docker/scout-sbom-indexer:latest provenance: mode=max # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps - # the vulnerable ca-certificates. Revert once every repo has been rebuilt and - # redeployed. See issue #953. + # the vulnerable ca-certificates. no-cache re-runs every step; pull re-resolves + # FROM, because no-cache alone leaves a base image that carries the bad package + # untouched. Revert once every repo has been rebuilt and redeployed. See #953. no-cache: true + pull: true cache-from: type=gha cache-to: type=gha,mode=max secrets: | diff --git a/src/build/docker-build-ts/action.yml b/src/build/docker-build-ts/action.yml index dd2b8a06..f521abfc 100644 --- a/src/build/docker-build-ts/action.yml +++ b/src/build/docker-build-ts/action.yml @@ -296,9 +296,11 @@ runs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps - # the vulnerable ca-certificates. Revert once every repo has been rebuilt and - # redeployed. See issue #953. + # the vulnerable ca-certificates. no-cache re-runs every step; pull re-resolves + # FROM, because no-cache alone leaves a base image that carries the bad package + # untouched. Revert once every repo has been rebuilt and redeployed. See #953. no-cache: true + pull: true cache-from: type=gha cache-to: type=gha,mode=max secrets: ${{ steps.secrets.outputs.value }} From 7ef33b4452ad5e6252968933d4f2b06909a70895 Mon Sep 17 00:00:00 2001 From: Lucas Bedatty <79675696+bedatty@users.noreply.github.com> Date: Wed, 21 Oct 2026 13:41:02 -0300 Subject: [PATCH 3/3] docs(build): say which rebuild ships the stale ca-certificates The note was in the present tense next to the line that disables the behaviour it describes, so it could read as if the no-cache build were the one keeping the bad package. Scope it to the cached rebuild. --- .github/workflows/build.yml | 8 ++++---- src/build/docker-build-ts/action.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 934d168a..0c6ec8ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -732,8 +732,8 @@ jobs: VERSION=${{ steps.version.outputs.version }} REVISION=${{ steps.source.outputs.sha }} BUILD_TIME=${{ steps.version.outputs.build_time }} - # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps - # the vulnerable ca-certificates. no-cache re-runs every step; pull re-resolves + # TEMPORARY: a cached rebuild replays the old apk/apt layer and would ship + # the vulnerable ca-certificates again. no-cache re-runs every step; pull re-resolves # FROM, because no-cache alone leaves a base image that carries the bad package # untouched. Revert once every repo has been rebuilt and redeployed. See #953. no-cache: true @@ -865,8 +865,8 @@ jobs: BUILD_TIME=${{ steps.version.outputs.build_time }} sbom: generator=docker/scout-sbom-indexer:latest provenance: mode=max - # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps - # the vulnerable ca-certificates. no-cache re-runs every step; pull re-resolves + # TEMPORARY: a cached rebuild replays the old apk/apt layer and would ship + # the vulnerable ca-certificates again. no-cache re-runs every step; pull re-resolves # FROM, because no-cache alone leaves a base image that carries the bad package # untouched. Revert once every repo has been rebuilt and redeployed. See #953. no-cache: true diff --git a/src/build/docker-build-ts/action.yml b/src/build/docker-build-ts/action.yml index f521abfc..ac2c547c 100644 --- a/src/build/docker-build-ts/action.yml +++ b/src/build/docker-build-ts/action.yml @@ -295,8 +295,8 @@ runs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - # TEMPORARY: the gha cache replays the old apk/apt layer, so a rebuild keeps - # the vulnerable ca-certificates. no-cache re-runs every step; pull re-resolves + # TEMPORARY: a cached rebuild replays the old apk/apt layer and would ship + # the vulnerable ca-certificates again. no-cache re-runs every step; pull re-resolves # FROM, because no-cache alone leaves a base image that carries the bad package # untouched. Revert once every repo has been rebuilt and redeployed. See #953. no-cache: true