From 7f286885de83fb92a34f879ed30f52d8906cc3cf Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Sat, 31 Oct 2026 15:30:51 +0100 Subject: [PATCH 1/4] fix(kyverno): bind the migration runtime to its release tag Stamp the executable with the reviewed v1.19.2 release and keep its symbols, so the build fails unless a scanner can read its true identity and reach package-level findings. Part of #5542 Co-Authored-By: Claude Opus 5.5 --- .../workflows/publish-kyverno-migration-runtime.yaml | 12 ++++++++++++ .../controllers/kyverno/MigrationRuntime.Dockerfile | 7 ++++++- scripts/tests/test-kyverno-migration-runtime.sh | 11 +++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-kyverno-migration-runtime.yaml b/.github/workflows/publish-kyverno-migration-runtime.yaml index 183bab655d..c3de89ea7d 100644 --- a/.github/workflows/publish-kyverno-migration-runtime.yaml +++ b/.github/workflows/publish-kyverno-migration-runtime.yaml @@ -65,6 +65,12 @@ jobs: git diff --check git add -- cmd/platform-migrate/main.go cmd/platform-migrate/main_test.go go.mod go.sum test "$(git write-tree)" = "${PATCHED_SOURCE_TREE}" + # Go stamps the main module version from a tag on a clean HEAD. Keep the source commit's date. + source_date="$(git log -1 --format=%cI)" + GIT_AUTHOR_DATE="${source_date}" GIT_COMMITTER_DATE="${source_date}" \ + git -c user.name=platform -c user.email=platform@devantler.tech commit --quiet --no-gpg-sign \ + --message "Apply reviewed migration runtime patch" + git tag v1.19.2 - name: Set up Buildx container driver uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0 @@ -129,6 +135,12 @@ jobs: git diff --check git add -- cmd/platform-migrate/main.go cmd/platform-migrate/main_test.go go.mod go.sum test "$(git write-tree)" = "${PATCHED_SOURCE_TREE}" + # Go stamps the main module version from a tag on a clean HEAD. Keep the source commit's date. + source_date="$(git log -1 --format=%cI)" + GIT_AUTHOR_DATE="${source_date}" GIT_COMMITTER_DATE="${source_date}" \ + git -c user.name=platform -c user.email=platform@devantler.tech commit --quiet --no-gpg-sign \ + --message "Apply reviewed migration runtime patch" + git tag v1.19.2 - name: Set up Buildx container driver uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0 diff --git a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile index 99489d772a..e17120aa55 100644 --- a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile +++ b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile @@ -13,9 +13,14 @@ RUN GOBIN=/usr/local/bin go install github.com/golangci/golangci-lint/v2/cmd/gol && timeout 300s golangci-lint run --timeout=4m ./cmd/platform-migrate ./cmd/cli/kubectl-kyverno/commands/migrate ARG VERSION=development RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=readonly -trimpath \ - -ldflags="-s -w -X main.buildVersion=${VERSION}" \ + -ldflags="-X main.buildVersion=${VERSION}" \ -o /out/kubectl-kyverno ./cmd/platform-migrate \ && test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1.26.10" \ + && go version -m /out/kubectl-kyverno > /tmp/build-info \ + && grep -Eq '^[[:space:]]+mod[[:space:]]+github\.com/kyverno/kyverno[[:space:]]+v1\.19\.2[[:space:]]' /tmp/build-info \ + && grep -Eq '^[[:space:]]+build[[:space:]]+vcs\.modified=false$' /tmp/build-info \ + && go tool nm /out/kubectl-kyverno > /tmp/symbols \ + && grep -Eq '[[:space:]]T main\.main$' /tmp/symbols \ && test "$(/out/kubectl-kyverno --version)" = "kubectl-kyverno version ${VERSION}" \ && /out/kubectl-kyverno migrate --help \ && if /out/kubectl-kyverno apply --help > /tmp/unsupported-command 2>&1; then \ diff --git a/scripts/tests/test-kyverno-migration-runtime.sh b/scripts/tests/test-kyverno-migration-runtime.sh index 1349ab46f0..429d2b6a05 100755 --- a/scripts/tests/test-kyverno-migration-runtime.sh +++ b/scripts/tests/test-kyverno-migration-runtime.sh @@ -31,6 +31,13 @@ for job in verify publish; do | map(select(. == "test \"$(git write-tree)\" = \"${PATCHED_SOURCE_TREE}\"")) | length) == 1)] | length == 1 ' "$workflow" >/dev/null || fail "exact source tree proof missing in $job" + # shellcheck disable=SC2016 + JOB="$job" yq -e ' + [.jobs[strenv(JOB)].steps[] | select(."working-directory" == "upstream") + | select((.run // "" | split("\n") + | map(select(. == "git tag v1.19.2")) + | length) == 1)] | length == 1 + ' "$workflow" >/dev/null || fail "release tag binding missing in $job" JOB="$job" yq -e '[.jobs[strenv(JOB)].steps[] | select(.with.repository == "kyverno/kyverno" and .with.ref == "e63308f1e16c05cd009ac4864be6ec25c66b49be" and .with."persist-credentials" == false)] | length == 1' "$workflow" >/dev/null || fail 'upstream checkout not exact' JOB="$job" yq -e '[.jobs[strenv(JOB)].steps[] | select(.with.file == "./k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile" and .with.provenance == "mode=max" and .with.sbom == true)] | length == 1' "$workflow" >/dev/null || fail 'tested build provenance missing' done @@ -54,6 +61,10 @@ grep -Fq 'test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1 # shellcheck disable=SC2016 grep -Fq 'test "$(/out/kubectl-kyverno --version)" = "kubectl-kyverno version ${VERSION}"' "$dockerfile" || fail 'actual immutable executable identity missing' grep -Fq 'unknown command "apply"' "$dockerfile" || fail 'unsupported-command refusal missing' +if grep -Eq -- '-ldflags="[^"]*-[sw][ "]' "$dockerfile"; then fail 'stripped symbols defeat the binary scan'; fi +grep -Fq 'github\.com/kyverno/kyverno[[:space:]]+v1\.19\.2[[:space:]]' "$dockerfile" || fail 'executable release identity proof missing' +grep -Fq 'vcs\.modified=false$' "$dockerfile" || fail 'clean source proof missing' +grep -Fq 'T main\.main$' "$dockerfile" || fail 'retained symbol proof missing' grep -Fxq 'FROM reg.kyverno.io/kyverno/kyverno-cli:v1.19.2@sha256:322ec5044d600930cb3af0e56dc33154a2d1d1fba58f4cadad3f47be7e78b11c' "$dockerfile" || fail 'runtime release pin changed' grep -Fxq 'USER 65534:65534' "$dockerfile" || fail 'migration Job execution identity changed' grep -Fxq 'RUN ["/ko-app/kubectl-kyverno", "migrate", "--help"]' "$dockerfile" || fail 'real non-root runtime check missing' From 9f413255f531702c56872d7be536e68d111631ca Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Sat, 31 Oct 2026 15:41:21 +0100 Subject: [PATCH 2/4] fix(kyverno): judge the migration runtime scan by exact advisory The retained symbols let the binary scan report Kyverno v1.19.2 whole-module records the repository already adjudicated. Accept only those exact IDs and require a symbol-level scan, so any other advisory fails the build. Part of #5542 Co-Authored-By: Claude Opus 5.5 --- .../controllers/kyverno/MigrationRuntime.Dockerfile | 10 +++++++++- scripts/tests/test-kyverno-migration-runtime.sh | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile index e17120aa55..7c6ea05982 100644 --- a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile +++ b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile @@ -26,9 +26,17 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=readonly -trimpath \ && if /out/kubectl-kyverno apply --help > /tmp/unsupported-command 2>&1; then \ echo 'Unsupported CLI command exposed by migration runtime'; exit 1; \ else test "$?" -eq 1 && grep -F 'unknown command "apply"' /tmp/unsupported-command; fi +# Only these exact whole-module records for Kyverno v1.19.2 are accepted, with the same +# adjudication and removal as scripts/tests/tenant-webapp-admission/.govulncheck-allow.txt +# (platform#5154). Any other advisory fails the build, and the scan must stay symbol-level. RUN GOBIN=/usr/local/bin go install golang.org/x/vuln/cmd/govulncheck@v1.8.0 \ && timeout 300s govulncheck ./cmd/platform-migrate \ - && timeout 120s govulncheck -mode=binary /out/kubectl-kyverno + && timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json \ + && grep -Eq '"scan_level": *"symbol"' /tmp/binary-scan.json \ + && grep -Eo '"osv": *"[^"]+"' /tmp/binary-scan.json | grep -Eo 'GO-[0-9]+-[0-9]+' | sort -u > /tmp/binary-findings \ + && if grep -Evx 'GO-2026-5594|GO-2026-5337|GO-2025-3615' /tmp/binary-findings; then \ + echo 'Unaccepted advisory in the compiled migration runtime'; exit 1; \ + else test "$?" -eq 1; fi FROM reg.kyverno.io/kyverno/kyverno-cli:v1.19.2@sha256:322ec5044d600930cb3af0e56dc33154a2d1d1fba58f4cadad3f47be7e78b11c COPY --from=builder --chmod=0755 /out/kubectl-kyverno /ko-app/kubectl-kyverno diff --git a/scripts/tests/test-kyverno-migration-runtime.sh b/scripts/tests/test-kyverno-migration-runtime.sh index 429d2b6a05..c7dd2586b2 100755 --- a/scripts/tests/test-kyverno-migration-runtime.sh +++ b/scripts/tests/test-kyverno-migration-runtime.sh @@ -55,7 +55,9 @@ grep -Fq "github.com/kyverno/kyverno/pkg/engine/|golang.org/x/crypto/openpgp|git grep -Fxq 'RUN timeout 300s go test -mod=readonly -race ./cmd/platform-migrate ./cmd/cli/kubectl-kyverno/commands/migrate' "$dockerfile" || fail 'released migration and actual TLS API regressions missing' grep -Fq 'go install golang.org/x/vuln/cmd/govulncheck@v1.8.0' "$dockerfile" || fail 'reviewed scanner missing' grep -Fq 'timeout 300s govulncheck ./cmd/platform-migrate' "$dockerfile" || fail 'source scan missing' -grep -Fq 'timeout 120s govulncheck -mode=binary /out/kubectl-kyverno' "$dockerfile" || fail 'compiled binary scan missing' +grep -Fq 'timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json' "$dockerfile" || fail 'compiled binary scan missing' +grep -Fq "grep -Eq '\"scan_level\": *\"symbol\"' /tmp/binary-scan.json" "$dockerfile" || fail 'symbol-level scan proof missing' +grep -Fq "grep -Evx 'GO-2026-5594|GO-2026-5337|GO-2025-3615' /tmp/binary-findings" "$dockerfile" || fail 'accepted advisories changed' # shellcheck disable=SC2016 grep -Fq 'test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1.26.10"' "$dockerfile" || fail 'actual compiler proof missing' # shellcheck disable=SC2016 From 0b1f7b66d4c69fe2bc0dcb4587869558d3d42018 Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Sat, 31 Oct 2026 16:12:08 +0100 Subject: [PATCH 3/4] fix(kyverno): prove the scanner extracted symbols from the runtime The recorded scan level is only what was requested, so also require a non-empty symbol list from the scanner extraction of the built binary. Part of #5542 Co-Authored-By: Claude Opus 5.5 --- .../controllers/kyverno/MigrationRuntime.Dockerfile | 2 ++ scripts/tests/test-kyverno-migration-runtime.sh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile index 7c6ea05982..04f5544dbd 100644 --- a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile +++ b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile @@ -33,6 +33,8 @@ RUN GOBIN=/usr/local/bin go install golang.org/x/vuln/cmd/govulncheck@v1.8.0 \ && timeout 300s govulncheck ./cmd/platform-migrate \ && timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json \ && grep -Eq '"scan_level": *"symbol"' /tmp/binary-scan.json \ + && timeout 120s govulncheck -mode=extract /out/kubectl-kyverno > /tmp/binary-extract.json \ + && grep -Eq '"pkgSymbols": *\[[^]]+\]' /tmp/binary-extract.json \ && grep -Eo '"osv": *"[^"]+"' /tmp/binary-scan.json | grep -Eo 'GO-[0-9]+-[0-9]+' | sort -u > /tmp/binary-findings \ && if grep -Evx 'GO-2026-5594|GO-2026-5337|GO-2025-3615' /tmp/binary-findings; then \ echo 'Unaccepted advisory in the compiled migration runtime'; exit 1; \ diff --git a/scripts/tests/test-kyverno-migration-runtime.sh b/scripts/tests/test-kyverno-migration-runtime.sh index c7dd2586b2..c6f5db5f35 100755 --- a/scripts/tests/test-kyverno-migration-runtime.sh +++ b/scripts/tests/test-kyverno-migration-runtime.sh @@ -57,6 +57,8 @@ grep -Fq 'go install golang.org/x/vuln/cmd/govulncheck@v1.8.0' "$dockerfile" || grep -Fq 'timeout 300s govulncheck ./cmd/platform-migrate' "$dockerfile" || fail 'source scan missing' grep -Fq 'timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json' "$dockerfile" || fail 'compiled binary scan missing' grep -Fq "grep -Eq '\"scan_level\": *\"symbol\"' /tmp/binary-scan.json" "$dockerfile" || fail 'symbol-level scan proof missing' +grep -Fq 'timeout 120s govulncheck -mode=extract /out/kubectl-kyverno > /tmp/binary-extract.json' "$dockerfile" || fail 'symbol extraction proof missing' +grep -Fq "grep -Eq '\"pkgSymbols\": *\\[[^]]+\\]' /tmp/binary-extract.json" "$dockerfile" || fail 'non-empty symbol proof missing' grep -Fq "grep -Evx 'GO-2026-5594|GO-2026-5337|GO-2025-3615' /tmp/binary-findings" "$dockerfile" || fail 'accepted advisories changed' # shellcheck disable=SC2016 grep -Fq 'test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1.26.10"' "$dockerfile" || fail 'actual compiler proof missing' From abddb6ec280e7ac449178d9258ac3264f0191d8b Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Sat, 31 Oct 2026 16:33:46 +0100 Subject: [PATCH 4/4] fix(kyverno): require the exact advisory list from the runtime scan An empty list passed the earlier filter, so a report the parser could not read looked clean. Require exactly the accepted records instead. Part of #5542 Co-Authored-By: Claude Opus 5.5 --- .../controllers/kyverno/MigrationRuntime.Dockerfile | 8 ++++---- scripts/tests/test-kyverno-migration-runtime.sh | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile index 04f5544dbd..ec169fc6db 100644 --- a/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile +++ b/k8s/bases/infrastructure/controllers/kyverno/MigrationRuntime.Dockerfile @@ -28,7 +28,8 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod=readonly -trimpath \ else test "$?" -eq 1 && grep -F 'unknown command "apply"' /tmp/unsupported-command; fi # Only these exact whole-module records for Kyverno v1.19.2 are accepted, with the same # adjudication and removal as scripts/tests/tenant-webapp-admission/.govulncheck-allow.txt -# (platform#5154). Any other advisory fails the build, and the scan must stay symbol-level. +# (platform#5154). The list must match exactly: another advisory fails the build, and so does +# an empty list, because that means the report was not read or the record needs removing here. RUN GOBIN=/usr/local/bin go install golang.org/x/vuln/cmd/govulncheck@v1.8.0 \ && timeout 300s govulncheck ./cmd/platform-migrate \ && timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyverno > /tmp/binary-scan.json \ @@ -36,9 +37,8 @@ RUN GOBIN=/usr/local/bin go install golang.org/x/vuln/cmd/govulncheck@v1.8.0 \ && timeout 120s govulncheck -mode=extract /out/kubectl-kyverno > /tmp/binary-extract.json \ && grep -Eq '"pkgSymbols": *\[[^]]+\]' /tmp/binary-extract.json \ && grep -Eo '"osv": *"[^"]+"' /tmp/binary-scan.json | grep -Eo 'GO-[0-9]+-[0-9]+' | sort -u > /tmp/binary-findings \ - && if grep -Evx 'GO-2026-5594|GO-2026-5337|GO-2025-3615' /tmp/binary-findings; then \ - echo 'Unaccepted advisory in the compiled migration runtime'; exit 1; \ - else test "$?" -eq 1; fi + && cat /tmp/binary-findings \ + && test "$(tr '\n' ' ' < /tmp/binary-findings)" = 'GO-2025-3615 GO-2026-5337 GO-2026-5594 ' FROM reg.kyverno.io/kyverno/kyverno-cli:v1.19.2@sha256:322ec5044d600930cb3af0e56dc33154a2d1d1fba58f4cadad3f47be7e78b11c COPY --from=builder --chmod=0755 /out/kubectl-kyverno /ko-app/kubectl-kyverno diff --git a/scripts/tests/test-kyverno-migration-runtime.sh b/scripts/tests/test-kyverno-migration-runtime.sh index c6f5db5f35..69e9a24aba 100755 --- a/scripts/tests/test-kyverno-migration-runtime.sh +++ b/scripts/tests/test-kyverno-migration-runtime.sh @@ -59,7 +59,8 @@ grep -Fq 'timeout 120s govulncheck -mode=binary -format json /out/kubectl-kyvern grep -Fq "grep -Eq '\"scan_level\": *\"symbol\"' /tmp/binary-scan.json" "$dockerfile" || fail 'symbol-level scan proof missing' grep -Fq 'timeout 120s govulncheck -mode=extract /out/kubectl-kyverno > /tmp/binary-extract.json' "$dockerfile" || fail 'symbol extraction proof missing' grep -Fq "grep -Eq '\"pkgSymbols\": *\\[[^]]+\\]' /tmp/binary-extract.json" "$dockerfile" || fail 'non-empty symbol proof missing' -grep -Fq "grep -Evx 'GO-2026-5594|GO-2026-5337|GO-2025-3615' /tmp/binary-findings" "$dockerfile" || fail 'accepted advisories changed' +# shellcheck disable=SC2016 +grep -Fq "test \"\$(tr '\\n' ' ' < /tmp/binary-findings)\" = 'GO-2025-3615 GO-2026-5337 GO-2026-5594 '" "$dockerfile" || fail 'accepted advisories changed' # shellcheck disable=SC2016 grep -Fq 'test "$(go version /out/kubectl-kyverno)" = "/out/kubectl-kyverno: go1.26.10"' "$dockerfile" || fail 'actual compiler proof missing' # shellcheck disable=SC2016