| name | sbom-supply-chain |
| type | skill |
| description | Generate, attach, and verify SBOMs (CycloneDX/SPDX) for container images; implement SLSA provenance; harden software supply chain. |
| related-rules | ["supply-chain-security.md (ci-cd)","shift-left-policy.md"] |
| allowed-tools | Read, Write, Edit, Bash |
Skill: SBOM & Supply Chain Security
Expertise: Syft/Trivy SBOM generation, cosign SBOM attestation, SLSA provenance, dependency pinning, OCI attestations.
When to load
When generating SBOMs for images, attaching attestations to OCI registry, verifying supply chain integrity, or achieving SLSA compliance.
SBOM Generation (Syft)
syft registry.example.com/myorg/order-service:v1.2.3 \
-o cyclonedx-json=sbom.cdx.json
syft registry.example.com/myorg/order-service:v1.2.3 \
-o spdx-json=sbom.spdx.json
syft dir:. -o cyclonedx-json=sbom.cdx.json
syft packages docker:myimage:latest -o cyclonedx-json=sbom.cdx.json
SBOM Attestation via cosign
docker buildx build --push \
-t registry.example.com/myorg/order-service:v1.2.3 .
DIGEST=$(crane digest registry.example.com/myorg/order-service:v1.2.3)
syft registry.example.com/myorg/order-service:v1.2.3 \
-o cyclonedx-json=sbom.cdx.json
cosign attest \
--predicate sbom.cdx.json \
--type cyclonedx \
registry.example.com/myorg/order-service@${DIGEST}
cosign verify-attestation \
--type cyclonedx \
--certificate-identity-regexp ".*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
registry.example.com/myorg/order-service@${DIGEST} \
| jq '.payload | @base64d | fromjson | .predicate.metadata'
GitHub Actions: Full Supply Chain Pipeline
jobs:
build-sign-attest:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Install syft
uses: anchore/sbom-action/download-syft@v0
- name: Build and push
id: build
uses: docker/build-push-action@v6
with:
push: true
tags: registry.example.com/myorg/order-service:${{ github.sha }}
- name: Sign image (keyless via OIDC)
run: |
cosign sign \
registry.example.com/myorg/order-service@${{ steps.build.outputs.digest }}
- name: Generate SBOM
run: |
syft registry.example.com/myorg/order-service@${{ steps.build.outputs.digest }} \
-o cyclonedx-json=sbom.cdx.json
- name: Attach SBOM attestation
run: |
cosign attest \
--predicate sbom.cdx.json \
--type cyclonedx \
registry.example.com/myorg/order-service@${{ steps.build.outputs.digest }}
- name: Generate SLSA provenance
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2
with:
image: registry.example.com/myorg/order-service
digest: ${{ steps.build.outputs.digest }}
Verify Before Deploy (admission check)
cosign verify \
--certificate-identity-regexp "https://github.com/myorg/myrepo" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
registry.example.com/myorg/order-service@sha256:<digest>
Dependency Pinning (supply chain hardening)
# Pin base image to digest — not just tag
FROM python:3.12-slim@sha256:abc123... # ✅
FROM python:3.12-slim # ❌ tag can be replaced
# Verify base image digest in CI
crane digest python:3.12-slim
pip-compile --generate-hashes requirements.in -o requirements.txt
pip install -r requirements.txt --require-hashes
npm ci
SBOM Analysis
grype sbom:sbom.cdx.json --fail-on high
cat sbom.cdx.json | jq '.components[] | {name: .name, version: .version, purl: .purl}'
cat sbom.cdx.json | jq '.components[] | select(.licenses[]?.license.id | startswith("GPL"))'