From 368e7fd864e8f399e3209216e3329c1936f51bbe Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 5 Aug 2026 14:03:25 +0100 Subject: [PATCH 1/6] oci-build: add oci-security-scan target and scheduled workflow Add an oci-scan- target for each OCI image and an oci-security-scan aggregate target, which scan the images using trivy for OS and library vulnerabilities which have a known fix and a severity of MEDIUM, HIGH or CRITICAL. The scan fails (exit code 1) if any such vulnerabilities are found, and prints a human readable report. Also generate a scheduled GitHub Actions workflow in downstream repositories, which runs oci-security-scan every night against the default branch, the two newest release branches and the latest release tag, to give early warning when released images, or images about to be released, contain fixable vulnerabilities. Signed-off-by: Richard Wall Co-Authored-By: Claude Fable 5 --- modules/oci-build/00_mod.mk | 2 + modules/oci-build/01_mod.mk | 38 +++++++++ .../.github/workflows/oci-security-scan.yaml | 78 +++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 modules/oci-build/base/.github/workflows/oci-security-scan.yaml diff --git a/modules/oci-build/00_mod.mk b/modules/oci-build/00_mod.mk index 71a444e2..f0c2bb8b 100644 --- a/modules/oci-build/00_mod.mk +++ b/modules/oci-build/00_mod.mk @@ -120,10 +120,12 @@ $(foreach build_name,$(build_names),$(eval $(call check_per_build_variables,$(bu # - oci-build-$(build_name)__local = build the oci directory (local arch: linux/$(HOST_ARCH)) # - oci-load-$(build_name) = load the image into docker using the oci_$(build_name)_image_name_development variable # - docker-tarball-$(build_name) = build a "docker load" compatible tarball of the image +# - oci-scan-$(build_name) = scan the image for known vulnerabilities using trivy oci_build_targets := $(build_names:%=oci-build-%) oci_build_targets += $(build_names:%=oci-build-%__local) oci_load_targets := $(build_names:%=oci-load-%) docker_tarball_targets := $(build_names:%=docker-tarball-%) +oci_scan_targets := $(build_names:%=oci-scan-%) # Derive config based on user config # diff --git a/modules/oci-build/01_mod.mk b/modules/oci-build/01_mod.mk index 026e46b8..c7a0c2f9 100644 --- a/modules/oci-build/01_mod.mk +++ b/modules/oci-build/01_mod.mk @@ -81,3 +81,41 @@ endif .PHONY: $(docker_tarball_targets) $(docker_tarball_targets): docker-tarball-%: oci-build-%__local | $(NEEDS_GO) $(NEEDS_IMAGE-TOOL) $(IMAGE-TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*).local $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) + +.PHONY: $(oci_scan_targets) +## Scan the OCI image (local architecture) for OS and library +## vulnerabilities which have a known fix and a severity of +## MEDIUM, HIGH or CRITICAL, using trivy +## (https://github.com/aquasecurity/trivy). +## @category [shared] Build +$(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) + $(TRIVY) image \ + --input $(docker_tarball_path_$*) \ + --severity MEDIUM,HIGH,CRITICAL \ + --ignore-unfixed \ + --exit-code 1 + +.PHONY: oci-security-scan +## Scan all the OCI images for known vulnerabilities, failing if any +## fixable vulnerabilities of severity MEDIUM, HIGH or CRITICAL are found. +## @category [shared] Build +oci-security-scan: $(oci_scan_targets) + +ifndef dont_generate_oci_security_scan + +oci_security_scan_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ + +.PHONY: generate-oci-security-scan +## Generate the scheduled GitHub Actions workflow which periodically runs +## oci-security-scan against the release branches and the latest release tag. +## @category [shared] Generate/ Verify +generate-oci-security-scan: + cp -r $(oci_security_scan_base_dir)/. ./ + cd $(oci_security_scan_base_dir) && \ + find . -type f | while read file; do \ + sed "s|{{REPLACE:GH-REPOSITORY}}|$(repo_name:github.com/%=%)|g" "$$file" > "$(CURDIR)/$$file"; \ + done + +shared_generate_targets += generate-oci-security-scan + +endif # dont_generate_oci_security_scan diff --git a/modules/oci-build/base/.github/workflows/oci-security-scan.yaml b/modules/oci-build/base/.github/workflows/oci-security-scan.yaml new file mode 100644 index 00000000..e6bd8877 --- /dev/null +++ b/modules/oci-build/base/.github/workflows/oci-security-scan.yaml @@ -0,0 +1,78 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/oci-build/base/.github/workflows/oci-security-scan.yaml instead. + +# Scan the OCI images built from the default branch, the release branches and +# the latest release tag every night, using trivy, to alert us when a released +# image, or an image we are about to release, contains fixable vulnerabilities +# of severity MEDIUM, HIGH or CRITICAL. +name: oci-security-scan +on: + workflow_dispatch: {} + schedule: + - cron: '0 2 * * *' + +permissions: + contents: read + +jobs: + list-refs: + runs-on: ubuntu-latest + + if: github.repository == '{{REPLACE:GH-REPOSITORY}}' + + outputs: + refs: ${{ steps.list-refs.outputs.refs }} + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: { fetch-depth: 0 } + + # Scan the branch this workflow runs on (the default branch), the two + # newest release branches, and the latest tag which is not a pre-release. + - id: list-refs + run: | + refs="$( + { + echo "${{ github.ref_name }}" + git branch --remotes --list 'origin/release-*' --format='%(refname:lstrip=3)' --sort=-version:refname \ + | grep -E '^release-[0-9]+\.[0-9]+$' | head -n 2 + git tag --list 'v*' --sort=-version:refname | grep -v '[-]' | head -n 1 + } | jq --raw-input . | jq --slurp --compact-output 'map(select(. != "")) | unique' + )" + echo "refs=${refs}" >> "$GITHUB_OUTPUT" + + oci-security-scan: + runs-on: ubuntu-latest + + needs: list-refs + + strategy: + fail-fast: false + matrix: + ref: ${{ fromJSON(needs.list-refs.outputs.refs) }} + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ matrix.ref }} + # Adding `fetch-depth: 0` makes sure tags are also fetched. We need + # the tags so `git describe` returns a valid version. + # see https://github.com/actions/checkout/issues/701 for extra info about this option + fetch-depth: 0 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: ${{ steps.go-version.outputs.result }} + + # Older release branches and tags may not have the oci-security-scan + # target yet; skip them rather than fail. + - run: | + if make --dry-run oci-security-scan >/dev/null 2>&1; then + make oci-security-scan + else + echo "::warning::The oci-security-scan target does not exist on ${{ matrix.ref }}; skipping." + fi From d510ee47092706b9119d64cafe31b678aaae465d Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 5 Aug 2026 16:19:41 +0100 Subject: [PATCH 2/6] Combine oci-security-scan into the nightly govulncheck workflow Instead of generating a second scheduled workflow file, extend the existing govulncheck workflow (shipped by the go module) into a single nightly security-scan workflow which runs verify-govulncheck and, where the repository builds OCI images, oci-security-scan. It scans the default branch, the two newest release branches and the latest release tag. The file keeps its historic govulncheck.yaml name so that GitHub continues to treat it as the same registered workflow, which means it can be triggered with workflow_dispatch on any branch (including pre-merge testing of this change), and no stale workflow files are left in downstream repositories. Signed-off-by: Richard Wall Co-Authored-By: Claude Fable 5 --- .../base/.github/workflows/govulncheck.yaml | 66 ++++++++++++++-- modules/oci-build/01_mod.mk | 19 ----- .../.github/workflows/oci-security-scan.yaml | 78 ------------------- 3 files changed, 58 insertions(+), 105 deletions(-) delete mode 100644 modules/oci-build/base/.github/workflows/oci-security-scan.yaml diff --git a/modules/go/base/.github/workflows/govulncheck.yaml b/modules/go/base/.github/workflows/govulncheck.yaml index 37a9f57a..9a264705 100644 --- a/modules/go/base/.github/workflows/govulncheck.yaml +++ b/modules/go/base/.github/workflows/govulncheck.yaml @@ -1,10 +1,17 @@ # THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. # Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. -# Run govulncheck at midnight every night on the main branch, -# to alert us to recent vulnerabilities which affect the Go code in this -# project. -name: govulncheck +# Nightly security scan. Runs govulncheck against the Go code and, where the +# repository builds OCI images, oci-security-scan, which uses trivy to check +# the images for fixable vulnerabilities of severity MEDIUM, HIGH or CRITICAL. +# Scans the default branch, the two newest release branches and the latest +# release tag, to give early warning when a released image, or an image we are +# about to release, contains known vulnerabilities. +# +# This file keeps its historic "govulncheck" name so that GitHub continues to +# treat it as the same registered workflow (which allows workflow_dispatch on +# any branch) and to avoid leaving stale workflow files in downstream repos. +name: security-scan on: workflow_dispatch: {} schedule: @@ -14,18 +21,52 @@ permissions: contents: read jobs: - govulncheck: + list-refs: runs-on: ubuntu-latest if: github.repository == '{{REPLACE:GH-REPOSITORY}}' + outputs: + refs: ${{ steps.list-refs.outputs.refs }} + steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - # Adding `fetch-depth: 0` makes sure tags are also fetched. We need - # the tags so `git describe` returns a valid version. - # see https://github.com/actions/checkout/issues/701 for extra info about this option with: { fetch-depth: 0 } + # Scan the branch this workflow runs on (usually the default branch), + # the two newest release branches, and the latest tag which is not a + # pre-release. + - id: list-refs + run: | + refs="$( + { + echo "${{ github.ref_name }}" + git branch --remotes --list 'origin/release-*' --format='%(refname:lstrip=3)' --sort=-version:refname \ + | grep -E '^release-[0-9]+\.[0-9]+$' | head -n 2 + git tag --list 'v*' --sort=-version:refname | grep -v '[-]' | head -n 1 + } | jq --raw-input . | jq --slurp --compact-output 'map(select(. != "")) | unique' + )" + echo "refs=${refs}" >> "$GITHUB_OUTPUT" + + security-scan: + runs-on: ubuntu-latest + + needs: list-refs + + strategy: + fail-fast: false + matrix: + ref: ${{ fromJSON(needs.list-refs.outputs.refs) }} + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ matrix.ref }} + # Adding `fetch-depth: 0` makes sure tags are also fetched. We need + # the tags so `git describe` returns a valid version. + # see https://github.com/actions/checkout/issues/701 for extra info about this option + fetch-depth: 0 + - id: go-version run: | make print-go-version >> "$GITHUB_OUTPUT" @@ -35,3 +76,12 @@ jobs: go-version: ${{ steps.go-version.outputs.result }} - run: make verify-govulncheck + + # Only repositories which build OCI images have the oci-security-scan + # target; older release branches and tags may not have it yet either. + - run: | + if make --dry-run oci-security-scan >/dev/null 2>&1; then + make oci-security-scan + else + echo "::notice::The oci-security-scan target does not exist on ${{ matrix.ref }}; skipping." + fi diff --git a/modules/oci-build/01_mod.mk b/modules/oci-build/01_mod.mk index c7a0c2f9..0fe3aa92 100644 --- a/modules/oci-build/01_mod.mk +++ b/modules/oci-build/01_mod.mk @@ -100,22 +100,3 @@ $(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) ## fixable vulnerabilities of severity MEDIUM, HIGH or CRITICAL are found. ## @category [shared] Build oci-security-scan: $(oci_scan_targets) - -ifndef dont_generate_oci_security_scan - -oci_security_scan_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ - -.PHONY: generate-oci-security-scan -## Generate the scheduled GitHub Actions workflow which periodically runs -## oci-security-scan against the release branches and the latest release tag. -## @category [shared] Generate/ Verify -generate-oci-security-scan: - cp -r $(oci_security_scan_base_dir)/. ./ - cd $(oci_security_scan_base_dir) && \ - find . -type f | while read file; do \ - sed "s|{{REPLACE:GH-REPOSITORY}}|$(repo_name:github.com/%=%)|g" "$$file" > "$(CURDIR)/$$file"; \ - done - -shared_generate_targets += generate-oci-security-scan - -endif # dont_generate_oci_security_scan diff --git a/modules/oci-build/base/.github/workflows/oci-security-scan.yaml b/modules/oci-build/base/.github/workflows/oci-security-scan.yaml deleted file mode 100644 index e6bd8877..00000000 --- a/modules/oci-build/base/.github/workflows/oci-security-scan.yaml +++ /dev/null @@ -1,78 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. -# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/oci-build/base/.github/workflows/oci-security-scan.yaml instead. - -# Scan the OCI images built from the default branch, the release branches and -# the latest release tag every night, using trivy, to alert us when a released -# image, or an image we are about to release, contains fixable vulnerabilities -# of severity MEDIUM, HIGH or CRITICAL. -name: oci-security-scan -on: - workflow_dispatch: {} - schedule: - - cron: '0 2 * * *' - -permissions: - contents: read - -jobs: - list-refs: - runs-on: ubuntu-latest - - if: github.repository == '{{REPLACE:GH-REPOSITORY}}' - - outputs: - refs: ${{ steps.list-refs.outputs.refs }} - - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: { fetch-depth: 0 } - - # Scan the branch this workflow runs on (the default branch), the two - # newest release branches, and the latest tag which is not a pre-release. - - id: list-refs - run: | - refs="$( - { - echo "${{ github.ref_name }}" - git branch --remotes --list 'origin/release-*' --format='%(refname:lstrip=3)' --sort=-version:refname \ - | grep -E '^release-[0-9]+\.[0-9]+$' | head -n 2 - git tag --list 'v*' --sort=-version:refname | grep -v '[-]' | head -n 1 - } | jq --raw-input . | jq --slurp --compact-output 'map(select(. != "")) | unique' - )" - echo "refs=${refs}" >> "$GITHUB_OUTPUT" - - oci-security-scan: - runs-on: ubuntu-latest - - needs: list-refs - - strategy: - fail-fast: false - matrix: - ref: ${{ fromJSON(needs.list-refs.outputs.refs) }} - - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - ref: ${{ matrix.ref }} - # Adding `fetch-depth: 0` makes sure tags are also fetched. We need - # the tags so `git describe` returns a valid version. - # see https://github.com/actions/checkout/issues/701 for extra info about this option - fetch-depth: 0 - - - id: go-version - run: | - make print-go-version >> "$GITHUB_OUTPUT" - - - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 - with: - go-version: ${{ steps.go-version.outputs.result }} - - # Older release branches and tags may not have the oci-security-scan - # target yet; skip them rather than fail. - - run: | - if make --dry-run oci-security-scan >/dev/null 2>&1; then - make oci-security-scan - else - echo "::warning::The oci-security-scan target does not exist on ${{ matrix.ref }}; skipping." - fi From b9569b772a833393cdbf8f8f030c2d152c00f69b Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 5 Aug 2026 16:20:03 +0100 Subject: [PATCH 3/6] Only run the trivy vulnerability scanner Skip the secret scanner, which is slow and not the purpose of this target. Signed-off-by: Richard Wall Co-Authored-By: Claude Fable 5 --- modules/oci-build/01_mod.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/oci-build/01_mod.mk b/modules/oci-build/01_mod.mk index 0fe3aa92..dbc6346d 100644 --- a/modules/oci-build/01_mod.mk +++ b/modules/oci-build/01_mod.mk @@ -91,6 +91,7 @@ $(docker_tarball_targets): docker-tarball-%: oci-build-%__local | $(NEEDS_GO) $( $(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) $(TRIVY) image \ --input $(docker_tarball_path_$*) \ + --scanners vuln \ --severity MEDIUM,HIGH,CRITICAL \ --ignore-unfixed \ --exit-code 1 From 4564294457c235cd1acc5ec25e2e1c12ddaa6b87 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 5 Aug 2026 16:37:34 +0100 Subject: [PATCH 4/6] Allow extra third party images to be scanned by oci-security-scan Some repositories (csi-driver, csi-driver-spiffe) deploy third party sidecar images alongside the images they build. List them in the new oci_scan_extra_images variable to have oci-security-scan scan them too. The trivy policy flags are factored into a trivy_scan_flags variable shared by all the scan targets. Signed-off-by: Richard Wall Co-Authored-By: Claude Fable 5 --- modules/oci-build/00_mod.mk | 16 ++++++++++++++++ modules/oci-build/01_mod.mk | 21 +++++++++++++++------ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/modules/oci-build/00_mod.mk b/modules/oci-build/00_mod.mk index f0c2bb8b..ab5d4b48 100644 --- a/modules/oci-build/00_mod.mk +++ b/modules/oci-build/00_mod.mk @@ -32,6 +32,22 @@ CGO_ENABLED ?= 0 GOEXPERIMENT ?= # empty by default oci_platforms ?= linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le +# Extra images (e.g. third party sidecar images which are deployed alongside +# the images built by this repository) to be scanned by oci-security-scan, +# for example: +# oci_scan_extra_images := registry.k8s.io/sig-storage/livenessprobe:v2.18.0 +oci_scan_extra_images ?= + +# The trivy policy applied by the oci-scan-* targets: report only +# vulnerabilities which have a known fix and a severity of MEDIUM, HIGH or +# CRITICAL, and fail if any are found. The secret scanner is disabled because +# it is slow. +trivy_scan_flags ?= \ + --scanners vuln \ + --severity MEDIUM,HIGH,CRITICAL \ + --ignore-unfixed \ + --exit-code 1 + # Default variables per build_names entry # # $1 - build_name diff --git a/modules/oci-build/01_mod.mk b/modules/oci-build/01_mod.mk index dbc6346d..57a2a166 100644 --- a/modules/oci-build/01_mod.mk +++ b/modules/oci-build/01_mod.mk @@ -91,13 +91,22 @@ $(docker_tarball_targets): docker-tarball-%: oci-build-%__local | $(NEEDS_GO) $( $(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) $(TRIVY) image \ --input $(docker_tarball_path_$*) \ - --scanners vuln \ - --severity MEDIUM,HIGH,CRITICAL \ - --ignore-unfixed \ - --exit-code 1 + $(trivy_scan_flags) + +.PHONY: oci-scan-extra-images +## Scan the images listed in oci_scan_extra_images (e.g. third party sidecar +## images which are deployed alongside the images built by this repository) +## for known vulnerabilities, using trivy. +## @category [shared] Build +oci-scan-extra-images: | $(NEEDS_TRIVY) + @for image in $(oci_scan_extra_images); do \ + echo "Scanning $$image"; \ + $(TRIVY) image $$image $(trivy_scan_flags) || exit 1; \ + done .PHONY: oci-security-scan -## Scan all the OCI images for known vulnerabilities, failing if any +## Scan all the OCI images built by this repository, and any extra images +## listed in oci_scan_extra_images, for known vulnerabilities; failing if any ## fixable vulnerabilities of severity MEDIUM, HIGH or CRITICAL are found. ## @category [shared] Build -oci-security-scan: $(oci_scan_targets) +oci-security-scan: $(oci_scan_targets) oci-scan-extra-images From 049ae805adc020f43e98f2fd5760ccc51dfa4598 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 5 Aug 2026 22:22:35 +0100 Subject: [PATCH 5/6] Write trivy scan reports to the GitHub job summary Trivy's table format is hard to read in the raw GitHub Actions job log because of line wrapping and timestamps. Append each scan report to $GITHUB_STEP_SUMMARY (inside a fenced code block, one heading per image) where it renders as fixed-width text on the run page. Only do this when GITHUB_STEP_SUMMARY is set, because some repos using this module run their CI on GitLab; there and locally the behaviour is unchanged (report on stdout, non-zero exit on findings). Signed-off-by: Richard Wall Co-Authored-By: Claude Fable 5 --- modules/oci-build/01_mod.mk | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/modules/oci-build/01_mod.mk b/modules/oci-build/01_mod.mk index 57a2a166..b64b094d 100644 --- a/modules/oci-build/01_mod.mk +++ b/modules/oci-build/01_mod.mk @@ -82,6 +82,26 @@ endif $(docker_tarball_targets): docker-tarball-%: oci-build-%__local | $(NEEDS_GO) $(NEEDS_IMAGE-TOOL) $(IMAGE-TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*).local $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) +# Run "trivy image $2 $(trivy_scan_flags)" and print the report to stdout. +# When running in GitHub Actions (detected by GITHUB_STEP_SUMMARY being set; +# some repos using this module run CI on GitLab instead) the report is also +# appended to the job summary under the heading $1, because trivy's table +# format is hard to read in the raw job log. +# +# $1 - summary heading +# $2 - trivy image arguments (an image reference or --input ) +define trivy_scan +report=$$(mktemp); \ +$(TRIVY) image $2 $(trivy_scan_flags) --output $$report; \ +code=$$?; \ +cat $$report; \ +if [ -n "$${GITHUB_STEP_SUMMARY:-}" ]; then \ + { echo "### $1"; echo '```'; cat $$report; echo '```'; echo; } >> "$$GITHUB_STEP_SUMMARY"; \ +fi; \ +rm -f $$report; \ +exit $$code +endef + .PHONY: $(oci_scan_targets) ## Scan the OCI image (local architecture) for OS and library ## vulnerabilities which have a known fix and a severity of @@ -89,9 +109,8 @@ $(docker_tarball_targets): docker-tarball-%: oci-build-%__local | $(NEEDS_GO) $( ## (https://github.com/aquasecurity/trivy). ## @category [shared] Build $(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) - $(TRIVY) image \ - --input $(docker_tarball_path_$*) \ - $(trivy_scan_flags) + @echo "Scanning $(oci_$*_image_name_development):$(oci_$*_image_tag)" + @$(call trivy_scan,$(oci_$*_image_name_development):$(oci_$*_image_tag),--input $(docker_tarball_path_$*)) .PHONY: oci-scan-extra-images ## Scan the images listed in oci_scan_extra_images (e.g. third party sidecar @@ -101,7 +120,15 @@ $(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) oci-scan-extra-images: | $(NEEDS_TRIVY) @for image in $(oci_scan_extra_images); do \ echo "Scanning $$image"; \ - $(TRIVY) image $$image $(trivy_scan_flags) || exit 1; \ + report=$$(mktemp); \ + $(TRIVY) image $$image $(trivy_scan_flags) --output $$report; \ + code=$$?; \ + cat $$report; \ + if [ -n "$${GITHUB_STEP_SUMMARY:-}" ]; then \ + { echo "### $$image"; echo '```'; cat $$report; echo '```'; echo; } >> "$$GITHUB_STEP_SUMMARY"; \ + fi; \ + rm -f $$report; \ + [ $$code -eq 0 ] || exit $$code; \ done .PHONY: oci-security-scan From 9f38f78fc9d3e9cdd00f57dc3202e82f9be2d123 Mon Sep 17 00:00:00 2001 From: Richard Wall Date: Wed, 5 Aug 2026 22:30:51 +0100 Subject: [PATCH 6/6] Scan all images even when an earlier scan finds vulnerabilities Previously oci-scan-extra-images exited at the first vulnerable image, so only the first report appeared in the log and job summary. Scan every image, then exit non-zero if any scan failed. Likewise run the workflow step with make --keep-going so a vulnerable built image does not prevent the remaining oci-scan-* prerequisites from running. Signed-off-by: Richard Wall Co-Authored-By: Claude Fable 5 --- modules/go/base/.github/workflows/govulncheck.yaml | 4 +++- modules/oci-build/01_mod.mk | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/modules/go/base/.github/workflows/govulncheck.yaml b/modules/go/base/.github/workflows/govulncheck.yaml index 9a264705..bcdb3883 100644 --- a/modules/go/base/.github/workflows/govulncheck.yaml +++ b/modules/go/base/.github/workflows/govulncheck.yaml @@ -79,9 +79,11 @@ jobs: # Only repositories which build OCI images have the oci-security-scan # target; older release branches and tags may not have it yet either. + # --keep-going so that one vulnerable image does not prevent the + # remaining images from being scanned and reported. - run: | if make --dry-run oci-security-scan >/dev/null 2>&1; then - make oci-security-scan + make --keep-going oci-security-scan else echo "::notice::The oci-security-scan target does not exist on ${{ matrix.ref }}; skipping." fi diff --git a/modules/oci-build/01_mod.mk b/modules/oci-build/01_mod.mk index b64b094d..494bf4c7 100644 --- a/modules/oci-build/01_mod.mk +++ b/modules/oci-build/01_mod.mk @@ -118,18 +118,18 @@ $(oci_scan_targets): oci-scan-%: docker-tarball-% | $(NEEDS_TRIVY) ## for known vulnerabilities, using trivy. ## @category [shared] Build oci-scan-extra-images: | $(NEEDS_TRIVY) - @for image in $(oci_scan_extra_images); do \ + @failed=0; \ + for image in $(oci_scan_extra_images); do \ echo "Scanning $$image"; \ report=$$(mktemp); \ - $(TRIVY) image $$image $(trivy_scan_flags) --output $$report; \ - code=$$?; \ + $(TRIVY) image $$image $(trivy_scan_flags) --output $$report || failed=1; \ cat $$report; \ if [ -n "$${GITHUB_STEP_SUMMARY:-}" ]; then \ { echo "### $$image"; echo '```'; cat $$report; echo '```'; echo; } >> "$$GITHUB_STEP_SUMMARY"; \ fi; \ rm -f $$report; \ - [ $$code -eq 0 ] || exit $$code; \ - done + done; \ + exit $$failed .PHONY: oci-security-scan ## Scan all the OCI images built by this repository, and any extra images