Stage 5 · Platform
Supply-Chain Security
Provenance Verification
Verifying SLSA attestations, GitHub artifact attestations, builder IDs, and source repository claims.
Verification Concept
Provenance verification confirms that an artifact was built by a trusted process from verified source code. Without verification, a signed artifact is meaningless — you need to check that the signature is valid, the certificate is trusted, and the identity matches expectations.
Verification answers: Was this artifact built from this source code? Was it built by this CI pipeline? Was the build process tamper-free? These answers prevent supply chain attacks where attackers substitute malicious builds.
SLSA Verification
jobs:
verify-and-deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
packages: read
steps:
- uses: actions/checkout@v4
- name: Install slsa-verifier
run: |
curl -sSfL https://github.com/slsa-framework/slsa-verifier/releases/latest/download/slsa-verifier-linux-amd64 -o slsa-verifier
chmod +x slsa-verifier
sudo mv slsa-verifier /usr/local/bin/
- name: Verify SLSA provenance
run: |
slsa-verifier verify-image \
ghcr.io/myorg/myapp:${{ github.event.client_payload.image_tag }} \
--source-uri github.com/myorg/myrepo \
--source-tag v1.0.0
- name: Deploy after verification
run: |
kubectl set image deployment/myapp \
myapp=ghcr.io/myorg/myapp:${{ github.event.client_payload.image_tag }} \
--namespace=productionslsa-verifier checks that the image was built from the specified source repository and tag. The source-uri and source-tag flags verify the source provenance. If verification fails, the deployment is not executed.
GitHub Attestation Verification
jobs:
verify-attestation:
runs-on: ubuntu-latest
permissions:
id-token: write
packages: read
steps:
- uses: actions/checkout@v4
- name: Install gh CLI
run: |
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update && sudo apt install gh -y
- name: Verify build provenance
run: |
gh attestation verify ghcr.io/myorg/myapp:${{ github.sha }} \
--owner myorg \
--predicate-type https://slsa.dev/provenance/v0.2
- name: Verify source provenance
run: |
gh attestation verify ghcr.io/myorg/myapp:${{ github.sha }} \
--owner myorg \
--source-ref refs/heads/maingh attestation verify checks that the artifact has a valid attestation from GitHub. The predicate-type flag specifies which attestation type to verify. The owner flag restricts verification to your organization's attestations.
Cosign Verification
jobs:
verify-image:
runs-on: ubuntu-latest
permissions:
packages: read
steps:
- uses: actions/checkout@v4
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Verify image signature
run: |
cosign verify \
--certificate-identity=https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/myorg/myapp:${{ github.sha }}
- name: Verify SBOM attestation
run: |
cosign verify-attestation \
--type cyclonedx \
--certificate-identity=https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/myorg/myapp:${{ github.sha }}
- name: Verify supply chain attestation
run: |
cosign verify-attestation \
--type slsaprovenance \
--certificate-identity=https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/myorg/myapp:${{ github.sha }}Cosign verifies the image signature, SBOM attestation, and SLSA provenance. The certificate-identity and certificate-oidc-issuer flags ensure the image was signed by the expected workflow from the expected OIDC provider.
Policy Enforcement
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
background: false
rules:
- name: check-image-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
issuer: "https://token.actions.githubusercontent.com"
subject: "https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main"
rekor:
url: https://rekor.sigstore.dev
attestations:
- type: https://slsa.dev/provenance/v0.2
conditions:
- all:
- key: "{{builder.id}}"
operator: Equals
value: "https://github.com/actions/runner"
- key: "{{buildType}}"
operator: Equals
value: "https://github.com/actions/workflow"Kyverno verifyImages checks that every image in a Pod has a valid signature from the expected identity. The attestation conditions verify the build type and builder. This prevents unsigned or unauthorized images from being deployed.
Admission Control
- Kyverno verifyImages — Kubernetes-native policy engine with built-in signature verification.
- OPA Gatekeeper — general-purpose policy engine that can verify attestations via Rego.
- Cosign webhook — standalone webhook that verifies signatures before admission.
- Sigstore Policy Controller — Kubernetes admission controller for Sigstore verification.
Combine multiple verification layers: sign at build time (cosign), verify in CI (slsa-verifier), verify at admission (Kyverno), and monitor at runtime (Rekor). No single layer is sufficient — defense in depth provides comprehensive protection.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.