From 20f80f944b458b00faacbbd32f32515e410628b4 Mon Sep 17 00:00:00 2001 From: Said Boudjelda Date: Sat, 24 Oct 2026 12:23:43 +0200 Subject: [PATCH] feat(ci): fetched chart dependencies must match pinned checksums Four charts vendor a chart fetched from outside this repository: seaweedfs 3.68.0 (kafka-cluster), litmus-core 3.28.1 (kates-chaos), kube-prometheus-stack 82.4.3 (monitoring) and strimzi-kafka-operator 1.2.0 (strimzi-operator, from quay.io). No Chart.lock is committed and nothing checked the bytes, so `helm dependency build` packed whatever those repositories served under the pinned version, and the publish job would sign it. charts/dependencies.sha256 now pins each archive, and the helm-deps action checks every chart it builds: - an archive that differs from its pin fails; - a pinned archive that is missing fails, so a dependency cannot move without its pin; - an archive with no pin fails, so a new dependency cannot arrive unpinned. Subcharts packed from charts/ (file://) are rebuilt on every run and are not pinned. The four hashes match the digests upstream publishes today: the seaweedfs, litmuschaos and prometheus-community index.yaml entries, and the chart layer of quay.io's strimzi-kafka-operator:1.2.0 manifest. --- .github/actions/helm-deps/action.yml | 27 ++++++++++++++++++++++++++- charts/dependencies.sha256 | 4 ++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 charts/dependencies.sha256 diff --git a/.github/actions/helm-deps/action.yml b/.github/actions/helm-deps/action.yml index c5aaf46c..81871633 100644 --- a/.github/actions/helm-deps/action.yml +++ b/.github/actions/helm-deps/action.yml @@ -4,7 +4,8 @@ description: >- `helm dependency build` for each requested chart, in the order given, with the repository's retry wrapper. Order matters for the umbrella: kates-platform packages its file:// subcharts as they are on disk, so their own dependencies - have to be built first. + have to be built first. Every archive fetched from outside this repository + must match its checksum in charts/dependencies.sha256. inputs: charts: description: Space-separated chart directory names under charts/, built in this order @@ -25,3 +26,27 @@ runs: echo "==> helm dependency build charts/${chart}/" scripts/retry.sh 5 helm dependency build "charts/${chart}/" done + + # A repository that serves different bytes under a version we pinned + # fails here, before anything renders or publishes them. Subcharts + # packed from charts/ (file://) are rebuilt on every run and are not + # pinned; every other archive must be. + pins=charts/dependencies.sha256 + for chart in ${CHARTS}; do + local_deps=$(sed -nE 's|^[[:space:]]*repository:[[:space:]]*"?file://\.\./([^"/[:space:]]+).*|\1|p' "charts/${chart}/Chart.yaml") + for tgz in "charts/${chart}"/charts/*.tgz; do + [[ -e "${tgz}" ]] || continue + for dep in ${local_deps}; do + [[ "$(basename "${tgz}")" == "${dep}-"[0-9]*.tgz ]] && continue 2 + done + if ! awk -v f="${tgz}" '$2 == f {found = 1} END {exit !found}' "${pins}"; then + echo "::error::${tgz} is not pinned. Check it against its repository's index digest, then add the line \`sha256sum ${tgz}\` prints to ${pins}" + exit 1 + fi + done + lines=$(awk -v p="charts/${chart}/charts/" 'index($2, p) == 1' "${pins}") + if [[ -n "${lines}" ]] && ! sha256sum -c - <<< "${lines}"; then + echo "::error::charts/${chart}: a fetched archive does not match ${pins}. Either its repository served different bytes under the same version, or the dependency moved without its pin. Check the new archive against the repository's index digest before changing the pin" + exit 1 + fi + done diff --git a/charts/dependencies.sha256 b/charts/dependencies.sha256 new file mode 100644 index 00000000..2a759f28 --- /dev/null +++ b/charts/dependencies.sha256 @@ -0,0 +1,4 @@ +af52bb05f0e63285477f9f0c3df0d8e8d353409d9de240058369d9f9267106e0 charts/kafka-cluster/charts/seaweedfs-3.68.0.tgz +09a0532275f45c4c5593f0a5d0317a6864e9884090eb1a8b2169f69be0f7616a charts/kates-chaos/charts/litmus-core-3.28.1.tgz +62d2fc381eeda4fb2bb8e63104d5cc1d192a3eaa53e7d0cc43fa3da97bfdb0b9 charts/monitoring/charts/kube-prometheus-stack-82.4.3.tgz +0f8a50b2f19bd99482f9fd6e17cf42902f72f9e594a136813ac3f0b7af422efd charts/strimzi-operator/charts/strimzi-kafka-operator-1.2.0.tgz