Secure the software supply chain from source to running container. Covers Cosign keyless image signing (Sigstore/Rekor), SBOM generation and attestation (Syft), vulnerability scanning with severity gates (Trivy/Grype), SLSA Level 2 provenance, and Kyverno/OPA admission enforcement. All open-source, no license cost. Use when asked to "sign my image", "generate an SBOM", "scan for CVEs", "attest build provenance", "enforce image signatures in Kubernetes", or "implement SLSA".
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
The canonical home for this skill is supply-chain in nitinjain999/platform-skills
Secure the software supply chain — from the build pipeline to running containers.
When invoked with no arguments, ask before proceeding:
Q1 — Mode?
What do you need?
1. audit — review an existing CI/CD pipeline for supply chain security gaps
2. sign — set up keyless image signing with Cosign (Sigstore/Rekor, no key management)
3. sbom — generate and attest an SBOM with Syft
4. scan — add a CVE vulnerability gate with Trivy or Grype
5. enforce — write a Kyverno policy to block unsigned images at admission
6. slsa — generate a SLSA Level 2 provenance workflow
Enter 1–6 or mode name:Q2 — Context (after mode selected, one at a time):
Paste your GitHub Actions workflow file(s) or describe your current CI/CD pipeline:Which container registry? (ECR / GHCR / Docker Hub / other):Which image and registry? (e.g. ghcr.io/org/image):Which scanner preference? Trivy (recommended) or Grype — or no preference:Which registry or image prefix should the policy cover? (e.g. ghcr.io/myorg/*):Which registry and repo? (e.g. ghcr.io/org/image from github.com/org/repo):Then proceed into the relevant mode below.
Review an existing CI/CD pipeline and cluster admission configuration for supply chain security gaps.
Steps:
[CRITICAL] No image signing — any image can be admitted to the cluster
[CRITICAL] No CVE severity gate — vulnerable images pass CI
[HIGH] No SBOM attestation — cannot audit what is running
[MEDIUM] Action versions pinned to tag, not SHAReference: references/supply-chain.md → Gap classification, Fix order
Set up keyless image signing with Cosign using Sigstore/Rekor (no key management required).
Steps:
- name: Install Cosign
uses: sigstore/cosign-installer@11086d9f32b178aa24e93c2b86eba3ef4b16b68a # v3.8.1
- name: Sign image
run: |
cosign sign --yes \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}cosign verify \
--certificate-identity-regexp="https://github.com/<org>/<repo>/.github/workflows/.*" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
ghcr.io/<org>/<image>@<digest>@sha256:…), never the tag — tags are mutableKey rules:
cosign-installer to a full SHA, e.g.: sigstore/cosign-installer@11086d9f32b178aa24e93c2b86eba3ef4b16b68aReference: references/supply-chain.md → Keyless signing, Rekor transparency log
Generate a Software Bill of Materials with Syft and attest it as an OCI artifact alongside the image.
Steps:
- name: Generate SBOM
uses: anchore/sbom-action@61119d458adab75f756bc0b9e4bde25725f86a7a # v0.20.0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: spdx-json
output-file: sbom.spdx.json
- name: Attest SBOM
run: |
cosign attest --yes \
--predicate sbom.spdx.json \
--type spdxjson \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}cosign download attestation \
--predicate-type https://spdx.dev/Document \
ghcr.io/<org>/<image>@<digest> | jq '.payload | @base64d | fromjson'spdx-json format for broadest tooling compatibility; cyclonedx-json is an alternativeReference: references/supply-chain.md → SBOM formats, Syft, Attestation
Add a CVE vulnerability scan with a configurable severity gate that fails the build.
Steps:
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@18f2135c0b15d26b3a4c2efded75e06b6f0e4884 # v0.30.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: table
exit-code: '1'
ignore-unfixed: true
vuln-type: os,library
severity: CRITICAL,HIGHignore-unfixed: true — skip CVEs with no fix available (reduces noise without reducing security)- name: Scan with Grype
uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7.4.0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
fail-build: true
severity-cutoff: highReference: references/supply-chain.md → Trivy vs Grype, Severity gates
Generate a Kyverno ImageValidatingPolicy that blocks unsigned or unverified images at admission time.
Finding where unsigned images already run: Kubescape reports them as control C-0237 "Check if signature exists" (/platform-skills:kubescape-operator, or kubescape scan control C-0237 on a cluster). Use that list to size the rollout before switching the policy to Deny.
Steps:
apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata:
name: require-signed-images
spec:
validationActions: [Audit] # switch to [Deny] after all images are signing
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
matchImageReferences:
- glob: "ghcr.io/<org>/*"
validations:
- expression: >
images.containers.map(image, verifyImageSignatures(image, [{"keyless": {
"url": "https://fulcio.sigstore.dev",
"rekor": {"url": "https://rekor.sigstore.dev"},
"identities": [{"issuer": "https://token.actions.githubusercontent.com",
"subjectRegExp": "https://github.com/<org>/.*"}]
}}])).all(e, e > 0)
message: "Image must be signed via Sigstore keyless signing from GitHub Actions"spec:
validationActions: [Audit] # start here, switch to [Deny] after validation/platform-skills:kyverno for full ImageValidatingPolicy guidanceReference: references/supply-chain.md → Kyverno enforcement, references/kyverno.md → ImageValidatingPolicy
Generate a GitHub Actions workflow for SLSA Level 2 provenance using slsa-github-generator.
Steps:
jobs:
build:
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.build.outputs.digest }}
permissions:
contents: read
packages: write
steps:
- name: Build and push image
id: build
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0
with:
push: true
tags: ghcr.io/<org>/<image>:${{ github.sha }}
provenance:
needs: build
permissions:
actions: read
id-token: write
packages: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@5a775b367a56d5bd118a224a811bba288150a563 # v2.0.0
with:
image: ghcr.io/<org>/<image>
digest: ${{ needs.build.outputs.digest }}
registry-username: ${{ github.actor }}
secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }}slsa-verifier verify-image \
ghcr.io/<org>/<image>@<digest> \
--source-uri github.com/<org>/<repo> \
--source-branch maingenerator_container_slsa3.yml produces L2 provenance by default; L3 requires hermetic builds not available on standard GitHub-hosted runnersReference: references/supply-chain.md → SLSA levels, slsa-github-generator
Signing and SBOMs cover what the pipeline produces. They say nothing about the pipeline itself — an unpinned uses: or a pull_request_target checkout of untrusted code compromises the build before any artifact exists. To audit the workflows that run this supply chain, including unpinned-uses hash-pin policy enforcement, use /platform-skills:zizmor. They also say nothing about whether a credential leaked into the repo that produces this artifact in the first place — for that, live-validate and revoke with /platform-skills:kingfisher.
After completing this task, log errors and learnings via /platform-skills:self-improve log.
nitinjain999/platform-skills
c2e75b7
Canonical home
since Oct 12, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.