Verifying Kubewarden SBOM Scanner

The Kubewarden SBOM Scanner project signs what it publishes, so that you can check that an artifact is the one the project built. For each release, the project publishes:

  • Signed container images, one per component.

  • A signed Software Bill of Materials (SBOM) and a signed provenance attestation for each image and architecture.

  • A signed Helm chart.

The signatures use Sigstore in keyless mode. The signing certificate names the GitHub Actions workflow that built the artifact. Each cosign command below passes two values:

  • --certificate-oidc-issuer: always https://token.actions.githubusercontent.com.

  • --certificate-identity: the workflow file and the Git ref of the release.

SBOM Scanner builds and signs with two workflows, so the identity differs by artifact type:

  • Container images: https://github.com/kubewarden/sbomscanner/.github/workflows/container-build.yml@refs/tags/v0.13.0

  • SBOM and provenance files on the release page: https://github.com/kubewarden/sbomscanner/.github/workflows/attestation.yml@refs/tags/v0.13.0

Use the exact identity, with the release tag, as the commands below do. A pattern such as https://github.com/kubewarden/* passed to --certificate-identity-regexp accepts an artifact from any workflow in any repository of the organization. The exact identity accepts only an artifact that the named workflow built.

The examples use the release v0.13.0 and the chart version 0.13.0. Replace them with the versions that you verify.

Container images

SBOM Scanner publishes four images, all at ghcr.io/kubewarden/sbomscanner/:

  • controller

  • worker

  • storage

  • mcp

The build workflow signs each single-architecture image and the multi-architecture index. To verify the controller image, run:

cosign verify \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity="https://github.com/kubewarden/sbomscanner/.github/workflows/container-build.yml@refs/tags/v0.13.0" \
  ghcr.io/kubewarden/sbomscanner/controller:v0.13.0

Verification for ghcr.io/kubewarden/sbomscanner/controller:v0.13.0 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority certificates

<snipped json>

The same command, with worker, storage, or mcp in place of controller, verifies the other images.

SBOM and provenance attestations

For each image and each architecture, the release workflow extracts an SBOM in SPDX format and a provenance attestation in SLSA format. It signs each file and attaches the files to the GitHub release. The names follow this pattern:

  • SBOMscanner-<component>-attestation-<arch>-provenance.intoto.jsonl

  • SBOMscanner-<component>-attestation-<arch>-sbom.json

Each file has a Sigstore bundle with the same name and the suffix .bundle.sigstore. Download the file and its bundle from the release page, then verify the provenance. Note the identity: these files are signed by the attestation.yml workflow, not by container-build.yml.

cosign verify-blob \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity="https://github.com/kubewarden/sbomscanner/.github/workflows/attestation.yml@refs/tags/v0.13.0" \
  --bundle SBOMscanner-controller-attestation-amd64-provenance.intoto.jsonl.bundle.sigstore \
  SBOMscanner-controller-attestation-amd64-provenance.intoto.jsonl

Verified OK

And the SBOM:

cosign verify-blob \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity="https://github.com/kubewarden/sbomscanner/.github/workflows/attestation.yml@refs/tags/v0.13.0" \
  --bundle SBOMscanner-controller-attestation-amd64-sbom.json.bundle.sigstore \
  SBOMscanner-controller-attestation-amd64-sbom.json

Verified OK

After the check, you can read the files. The SBOM lists the packages in the image. The provenance names the source commit, the builder, and the build parameters.

The same attestations are also attached to each image in the registry, in the format that Docker uses. The signed copies are the release assets. To read the registry copy, list the attestation manifest with crane:

crane manifest ghcr.io/kubewarden/sbomscanner/controller:v0.13.0 \
  | jq '.manifests[] | select(.annotations["vnd.docker.reference.type"]=="attestation-manifest")'

Then fetch the manifest by its digest and read each layer with crane blob.

Helm chart

The SBOM Scanner chart is in the Helm repository at https://charts.kubewarden.io and, as an OCI artifact, at ghcr.io/kubewarden/charts/sbomscanner. The OCI copy is signed. The chart is released from the kubewarden/helm-charts repository, so the identity names that workflow:

cosign verify \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity="https://github.com/kubewarden/helm-charts/.github/workflows/helm-chart-release.yml@refs/heads/main" \
  ghcr.io/kubewarden/charts/sbomscanner:0.13.0

Verification for ghcr.io/kubewarden/charts/sbomscanner:0.13.0 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The code-signing certificate was verified using trusted certificate authority certificates

<snipped json>

The chart also has a GitHub build provenance attestation. The GitHub CLI verifies it:

gh attestation verify oci://ghcr.io/kubewarden/charts/sbomscanner:0.13.0 \
  --repo kubewarden/helm-charts

To list every image that the chart deploys, render it and extract the image fields:

helm template sbomscanner oci://ghcr.io/kubewarden/charts/sbomscanner \
  --version 0.13.0 \
  | yq '..|.image? | select(.)' \
  | sort -u

Verify each SBOM Scanner image in that list as the container images section shows.

Third-party images

The chart also deploys images that the SBOM Scanner project does not build and does not sign:

  • The NATS server and its configuration reloader, from the nats subchart.

  • The PostgreSQL image that the CloudNativePG operator runs, when storage.postgres.cnpg.enabled is true.

The worker also pulls the Trivy vulnerability databases from public.ecr.aws/aquasecurity/ as OCI artifacts. Verify these with the method that their own projects document.