Verify Kubernetes Release Binaries and Container Images

Download official Kubernetes release artifacts, verify SHA256 checksums and Cosign signatures on kubectl binaries and SPDX SBOMs, validate signed control-plane images, and record digests before install or deployment.

Published

Updated

Read time 8 min read

Reviewed byDeepak Prasad

Cosign and checksum verification of official Kubernetes kubectl binaries and control-plane container images
Tested on Rocky Linux 10.2 (Red Quartz) workstation
Package cosign 2.4.1
kubectl v1.36.3 (verified download)
Applies to Ubuntu, Debian, Kali Linux, Linux Mint, Pop!_OS, Raspberry Pi OS, elementary OS, Zorin OS, Parrot OS, MX Linux, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora
Kubernetes cluster
Cert prep CKS
Privilege Normal user for download and verification; sudo to install binaries under /usr/local/bin
Scope Resolve and record a Kubernetes release version, verify kubectl checksums and Cosign signatures, validate a signed control-plane image and release SPDX SBOM, demonstrate common failure modes, and build a repeatable verification workflow. Does not cover signing your own application images, building Kubernetes from source, private registry configuration, vulnerability scanning, or CI/CD promotion pipelines.
Related guides Kubernetes CIS benchmark with kube-bench
Kubernetes PKI and certificates

Before you copy kubectl into /usr/local/bin or roll out a new control-plane image, confirm the bytes match the official release and were signed by Kubernetes release engineering. This walkthrough verifies one standalone binary, one release SPDX SBOM, and one signed kube-apiserver image for Kubernetes v1.36.3 on linux/amd64.

IMPORTANT
This guide covers official Kubernetes release artifacts from dl.k8s.io, sbom.k8s.io, and registry.k8s.io. It does not teach Cosign for your own application images, run Trivy or other vulnerability scanners, or configure private registries. For workload signing workflows, see Cosign sign and verify container images.

Understand the verification layers

Supply-chain checks stack from fast integrity tests to publisher identity and immutable image references:

Verification Question answered
Checksum Do these bytes match the published file?
Signature Was the artifact signed by the expected identity?
Digest Is this the exact immutable container image?
SBOM What components does this release declare?

A matching SHA256 hash tells you the file on disk equals the hash file you downloaded. It does not independently prove who published the binary—an attacker who replaces both files on a mirror defeats checksum-only checks. Cosign signature verification pins the certificate identity and OIDC issuer Kubernetes documents for release engineering.


Select an official release

Record the resolved version before you download anything. Do not silently follow stable.txt in automation; write down the exact tag you validated.

For this lab I pin:

Field Value
Kubernetes version v1.36.3
Operating system linux
CPU architecture amd64
Release channel Official GA from dl.k8s.io
Binary base URL https://dl.k8s.io/release/v1.36.3/bin/linux/amd64
SBOM URL https://sbom.k8s.io/v1.36.3/release
Control-plane image registry.k8s.io/kube-apiserver-amd64:v1.36.3

Create a clean working directory so verification files stay beside the artifact they describe:

bash
mkdir -p ~/k8s-verify && cd ~/k8s-verify
export VERSION=v1.36.3
export URL="https://dl.k8s.io/release/${VERSION}/bin/linux/amd64"

Install Cosign on the workstation

Binary and SBOM signature checks use Cosign. Install a current release before you download Kubernetes artifacts:

bash
curl -sSfL "https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64" -o cosign
chmod +x cosign
sudo mv cosign /usr/local/bin/cosign

Confirm the client version:

bash
cosign version
output
GitVersion:    v2.4.1
GitCommit:     9a4cfe1aae777984c07ce373d97a65428bbff734
Platform:      linux/amd64

Cosign 2.4.x matches the flags used in the current Kubernetes release documentation.


Download the binary and verification files

Download kubectl plus the sidecar files Kubernetes publishes for signature verification. Do not execute the binary until checksum and signature checks pass.

bash
export BINARY=kubectl
curl -sSfL "${URL}/${BINARY}" -o "${BINARY}"

Fetch the checksum and Cosign certificate bundle:

bash
curl -sSfL "${URL}/${BINARY}.sha256" -o "${BINARY}.sha256"
curl -sSfL "${URL}/${BINARY}.sig" -o "${BINARY}.sig"
curl -sSfL "${URL}/${BINARY}.cert" -o "${BINARY}.cert"

List the files and read the published hash:

bash
ls -l kubectl kubectl.sha256 kubectl.sig kubectl.cert
cat kubectl.sha256
output
-rw-r--r--. 1 user user 59556002 Jul 28 03:09 kubectl
-rw-r--r--. 1 user user     1508 Jul 28 03:09 kubectl.cert
-rw-r--r--. 1 user user       64 Jul 28 03:09 kubectl.sha256
-rw-r--r--. 1 user user       96 Jul 28 03:09 kubectl.sig
ebbd080e7c2e275093b55915722043257eb24004363e20acb3c4d71919f88336

The .sha256 file contains only the hex digest. The .sig and .cert files feed cosign verify-blob in the next sections.


Verify the checksum

Format the hash line as digest filename before you run sha256sum --check:

bash
echo "$(cat kubectl.sha256)  kubectl" | sha256sum --check -
output
kubectl: OK

When the bytes match, sha256sum prints OK and exits zero.

To see what a tampered file looks like, append one byte and rerun the same check:

bash
echo "X" >> kubectl
echo "$(cat kubectl.sha256)  kubectl" | sha256sum --check -
output
kubectl: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

Restore the good copy from your download cache or re-fetch the binary before you continue—signature verification will fail on a modified file.

bash
curl -sSfL "${URL}/kubectl" -o kubectl

Verify the binary signature

Kubernetes signs release binaries with Cosign keyless signatures. Pin the certificate identity and OIDC issuer from the verify signed artifacts task documentation:

Run cosign verify-blob against the untouched binary:

bash
cosign verify-blob kubectl \
  --certificate kubectl.cert \
  --signature kubectl.sig \
  --certificate-identity [email protected] \
  --certificate-oidc-issuer https://accounts.google.com
output
Verified OK

Verified OK means the signature matches the blob and the certificate subject matches the identity you pinned.


Inspect the verified binary

After checksum and signature checks succeed, confirm the artifact is the executable you expect:

bash
file kubectl
output
kubectl: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=..., stripped

Make it executable and read the client version:

bash
chmod +x kubectl
./kubectl version --client
output
Client Version: v1.36.3
Kustomize Version: v5.8.1

Install only after these checks pass:

bash
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Verify a Kubernetes container image

Control-plane images use a different certificate identity than binaries:

Verify the signed kube-apiserver image for the same release:

bash
cosign verify registry.k8s.io/kube-apiserver-amd64:v1.36.3 \
  --certificate-identity [email protected] \
  --certificate-oidc-issuer https://accounts.google.com

Cosign prints a JSON payload on success. The docker-manifest-digest field is the immutable digest to record:

output
Verification for registry.k8s.io/kube-apiserver-amd64:v1.36.3 --
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
...
"docker-manifest-digest":"sha256:9ab60d55c6fce46d71ff56b9196529c8afd34700ea9be1a444b8b60f8cf14b34"
...
"Subject":"[email protected]"

Store that digest in your install record. When you deploy, prefer the digest form:

text
registry.k8s.io/kube-apiserver-amd64@sha256:9ab60d55c6fce46d71ff56b9196529c8afd34700ea9be1a444b8b60f8cf14b34

Your container runtime may also show a config digest after crictl pull; the manifest digest from Cosign is what you pin for reproducible promotion.


Verify the Kubernetes SBOM

Kubernetes publishes a signed SPDX SBOM per release. Download the document and its verification files:

bash
export SBOM_URL="https://sbom.k8s.io/${VERSION}/release"
curl -sSfL "${SBOM_URL}" -o sbom-release
curl -sSfL "${SBOM_URL}.sha256" -o sbom-release.sha256
curl -sSfL "${SBOM_URL}.sha512" -o sbom-release.sha512
curl -sSfL "${SBOM_URL}.sig" -o sbom-release.sig
curl -sSfL "${SBOM_URL}.cert" -o sbom-release.cert

Verify the SHA256 checksum:

bash
echo "$(cat sbom-release.sha256)  sbom-release" | sha256sum --check -
output
sbom-release: OK

Verify the SPDX signature with the same binary identity as kubectl:

bash
cosign verify-blob sbom-release \
  --certificate sbom-release.cert \
  --signature sbom-release.sig \
  --certificate-identity [email protected] \
  --certificate-oidc-issuer https://accounts.google.com
output
Verified OK

Inspect release metadata at the top of the SPDX file:

bash
head -8 sbom-release
output
SPDXVersion: SPDX-2.3
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: Kubernetes Release v1.36.3
DocumentNamespace: https://sbom.k8s.io/v1.36.3/release
ExternalDocumentRef:DocumentRef-kubernetes-v1.36.3 https://sbom.k8s.io/v1.36.3/source SHA1: 88a3eb05437b148a79bdbcfc1ea4f1d804ca1292
Creator: Organization: Kubernetes Release Engineering
Creator: Tool: bom-v0.21.1

Archive the verified SPDX file, checksum output, and Cosign transcript with your cluster upgrade ticket.


Test failure conditions

Deliberately break one control at a time so you recognize real errors in automation.

Modified binary or wrong checksum

Appending bytes to kubectl makes sha256sum --check report FAILED as shown earlier. Re-download before signature checks.

Wrong signer identity

Pinning the wrong email makes Cosign reject the certificate:

bash
cosign verify-blob kubectl \
  --certificate kubectl.cert \
  --signature kubectl.sig \
  --certificate-identity [email protected] \
  --certificate-oidc-issuer https://accounts.google.com
output
Error: none of the expected identities matched what was in the certificate, got subjects [[email protected]] with issuer https://accounts.google.com

The message names the subject actually present in the certificate—compare it to the value in Kubernetes documentation.

Wrong OIDC issuer

An incorrect issuer also fails verification:

bash
cosign verify-blob kubectl \
  --certificate kubectl.cert \
  --signature kubectl.sig \
  --certificate-identity [email protected] \
  --certificate-oidc-issuer https://evil.example.com
output
Error: searching log query: ... verifying signature: invalid signature when validating ASN.1 encoded signature

Treat any non-zero exit from cosign verify or verify-blob as a hard stop.

Unsigned or wrong image

Public images outside the Kubernetes release pipeline carry no matching signature:

bash
cosign verify docker.io/library/nginx:latest \
  --certificate-identity [email protected] \
  --certificate-oidc-issuer https://accounts.google.com
output
Error: no signatures found

Deploying by digest still requires that you verified that digest. Pulling sha256:9ab60d55... after validating v1.36.3 is sound; substituting a different digest without re-verification is not.


Build a verification workflow

The diagram below is the repeatable order of operations for install or upgrade evidence:

Kubernetes release verification workflow from version resolution through checksum, signature, architecture check, install, and digest recording

Resolve the version explicitly, download artifacts and sidecars together, verify checksum then signature, confirm architecture and client version, install or deploy, and store digests plus Cosign output. Automate the same sequence in CI with pinned identities—not only on the admin laptop.


Troubleshooting

Symptom Likely cause Fix
sha256sum: no properly formatted checksum lines found .sha256 file contains only the hex digest Pipe echo "$(cat file.sha256) filename" | sha256sum --check -
Verified OK missing after verify-blob Binary modified or wrong .sig/.cert pair Re-download binary and sidecars; do not run a tampered binary
Identity mismatch error from Cosign Wrong --certificate-identity for artifact type Use krel-staging@... for binaries and SBOM; krel-trust@... for images
no signatures found on image verify Image is not part of the signed Kubernetes release set Confirm repository name and tag; do not expect signatures on arbitrary public images
Cosign cannot reach transparency log Offline host or firewall Use documented offline verification flags from Cosign and Kubernetes docs when air-gapped

What's Next


References


Summary

You walked through the full release verification stack for Kubernetes v1.36.3: checksum integrity on kubectl, Cosign keyless signatures that pin [email protected] for binaries and SBOMs, and [email protected] for the signed kube-apiserver-amd64 image. Recording the resolved version, manifest digest, and verification transcripts gives you evidence for audits and incident response.

The distinction that trips many teams is checksum versus signature. SHA256 catches corrupted or casually swapped files but does not prove publisher identity on its own. Cosign ties the artifact to the release engineering service accounts Kubernetes documents, which is what you want before binaries land on admin hosts or images enter a production registry mirror.

Run the failure demos once so automation alerts look familiar—identity mismatch, bad issuer, and no signatures found should halt promotion immediately. For where supply-chain controls sit in the broader security model, see Kubernetes security architecture. When you move from verifying upstream releases to signing your own workload images, continue with Cosign sign and verify container images.


Frequently Asked Questions

1. Is a SHA256 checksum enough to trust a Kubernetes binary?

A checksum proves the file you downloaded matches the hash published alongside the release, which catches transport corruption and casual tampering. It does not prove the publisher identity on its own—anyone who can replace the binary can also publish a matching hash on the same page. Pair checksum verification with Cosign signature checks that pin the expected Kubernetes release engineering identity and OIDC issuer.

2. Which Cosign identity signs Kubernetes release binaries?

Release binaries and SPDX SBOM files are signed with certificate identity [email protected] and OIDC issuer https://accounts.google.com. Official control-plane container images use [email protected] with the same issuer. Pin these values from the current Kubernetes verify-signed-artifacts documentation when you automate checks.

3. Should I verify Kubernetes images by tag or by digest?

Verify the image reference you plan to deploy, then record the immutable digest from the Cosign verification output or your container runtime. Tags such as v1.36.3 can be repointed; digests cannot. Store the digest in install records, Helm values, or GitOps manifests so later pulls resolve the exact bytes you validated.

4. When should I verify the Kubernetes release SBOM?

Download and verify the SPDX SBOM for the same release version you install, alongside the binaries and images you promote. The SBOM lists declared components for audit and incident response. Keep the verified SPDX file, its checksum evidence, and signature output with your change ticket so you can answer what shipped in a given cluster upgrade.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)