Skip to content

Software Supply Chain Security: SBOM, SLSA, and Artifact Signing for Developers

Karify98 & Amy ๐ŸŒธยท
Cover Image for Software Supply Chain Security: SBOM, SLSA, and Artifact Signing for Developers

Have you ever wondered: is the binary running in production actually built from the exact source code your team reviewed? Or did someone inject something between pipeline stages?

SolarWinds, Log4Shell, the xz utils backdoor โ€” every major supply chain incident proves the same point: securing your code isn't enough. You need to secure everything that touches your code. Dependencies, build systems, artifact registries, deployment pipelines โ€” every link is a potential attack vector.

In 2026, supply chain security is no longer optional. US Executive Order 14028 and the EU Cyber Resilience Act now mandate SBOMs for software sold to government agencies. Major cloud providers require SLSA compliance for marketplace listings. Enterprise customers are starting to demand provenance attestations.

This guide covers the three pillars of supply chain security โ€” SBOM, SLSA, and artifact signing โ€” with practical, no-nonsense implementation.

The Attack Surface: You Don't Know What You're Running

Answer these honestly:

  • Can you list every dependency โ€” including transitives โ€” in your production containers?
  • Can you prove the binary in production was built from the exact source code you reviewed?
  • Can you verify no one modified the artifact between your CI pipeline and your production cluster?

If you answered "no" to any of these, your supply chain has gaps attackers can exploit.

The simplified model:

Source Code โ†’ Build System โ†’ Package Registry โ†’ Container Registry โ†’ Production
     โ†‘            โ†‘                โ†‘                  โ†‘               โ†‘
 Malicious    Compromised    Typosquatting       Image          Runtime
  commits      CI runner      packages         tampering       injection

The three pillars below address each link in this chain.

Pillar 1: SBOM โ€” Know What's Inside

An SBOM (Software Bill of Materials) is a complete, machine-readable inventory of every component in your software. Think of it as a nutritional label for code.

A standard SBOM includes:

  • Every direct and transitive dependency with versions
  • Licenses for each component
  • Supplier information
  • Known CVEs (when cross-referenced with vulnerability databases)

Two Main Formats

  • SPDX (Software Package Data Exchange): ISO/IEC 5962:2021 standard, maintained by the Linux Foundation. Preferred by US government agencies.
  • CycloneDX: Maintained by OWASP, focused on security use cases. More practical for internal security.

Generate SBOMs in CI/CD

The most popular tools are Syft (Anchore) and Trivy (Aqua Security):

# Generate SBOM for a container image
syft registry.example.com/myapp:v1.0 -o spdx-json > sbom.spdx.json

# Generate SBOM + vulnerability scan with Trivy
trivy image --format cyclonedx --output sbom.cdx.json myapp:v1.0

GitHub Actions integration:

name: Build with SBOM
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .
      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          image: myapp:${{ github.sha }}
          format: spdx-json
      - name: Scan SBOM for vulnerabilities
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'image'
          image-ref: 'myapp:${{ github.sha }}'
          format: 'table'
          severity: 'CRITICAL,HIGH'
          exit-code: 1

This flow ensures: every push to main generates an SBOM with vulnerability scan results. Critical CVEs fail the pipeline โ€” no merge possible.

Pillar 2: SLSA โ€” Prove It Was Built Correctly

SLSA (Supply-chain Levels for Software Artifacts, pronounced "salsa") is a framework defining build integrity levels. It answers: "Can you prove this artifact was built from this source code, using this build process, without tampering?"

The Four SLSA Levels

  • Level 0: No guarantees. Build on your laptop, push directly. No provenance, no verification.
  • Level 1: Provenance attestation exists โ€” a signed document stating which commit, date, and build system produced this artifact. Not yet tamper-proof.
  • Level 2: Build runs on a hosted service (GitHub Actions, Cloud Build) with provenance signed by the platform itself. Prevents provenance falsification.
  • Level 3: Build runs in an isolated, ephemeral environment. No one โ€” including maintainers โ€” can inject material into the build without it being recorded.

Practical target: Level 2 for most projects, Level 3 for critical software.

GitHub Actions Built-in SLSA Support

name: Build with SLSA
on:
  push:
    tags: ['v*']
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
      attestations: write
    steps:
      - uses: actions/checkout@v4
      - name: Build and push
        id: build
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
      - name: Generate SLSA provenance
        uses: actions/attest-build-provenance@v2
        with:
          subject-name: ghcr.io/${{ github.repository }}
          subject-digest: ${{ steps.build.outputs.digest }}
          push-to-registry: true

This workflow automatically generates a signed attestation proving which repo, commit, and workflow produced the artifact.

Verifying Provenance

Anyone can verify with GitHub CLI:

gh attestation verify oci://ghcr.io/myorg/myapp:v1.0 --owner myorg

Pillar 3: Cosign โ€” Sign Artifacts, Prevent Tampering

Cosign is a tool from the Sigstore project for signing container images and any OCI artifacts. It answers the final question: "Was this artifact modified after the build?"

Keyless Signing with OIDC

The simplest approach โ€” no private key management needed:

# Sign image using OIDC identity from GitHub Actions
cosign sign ghcr.io/myorg/myapp:v1.0

In CI pipeline:

- name: Sign container image
  uses: sigstore/cosign-installer@v3
- run: |
    cosign sign \
      --certificate-identity-regexp "https://github.com/${{ github.repository }}" \
      --certificate-oidc-issuer https://token.actions.githubusercontent.com \
      ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

Verify Before Deploying

cosign verify \
  --certificate-identity-regexp "https://github.com/myorg/myapp" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/myorg/myapp:v1.0

This should be integrated into your Kubernetes admission controller (e.g., Kyverno or OPA Gatekeeper) to reject any unsigned images from being deployed. That's the final enforcement point โ€” theory becomes reality.

Putting It All Together: A Complete Pipeline

Here's a full pipeline combining SBOM + SLSA + Cosign:

name: Secure Build Pipeline
on:
  push:
    tags: ['v*']
permissions:
  contents: read
  id-token: write
  attestations: write
  packages: write

jobs:
  secure-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: false
          load: true
          tags: myapp:${{ github.sha }}

      # Pillar 1: Generate SBOM
      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          image: myapp:${{ github.sha }}
          format: spdx-json
          output-file: sbom.spdx.json

      - name: Scan vulnerabilities
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          format: table
          severity: CRITICAL
          exit-code: 1

      # Push after scan passes
      - name: Push image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      # Pillar 2: SLSA Provenance
      - name: Generate provenance
        uses: actions/attest-build-provenance@v2
        with:
          subject-name: ghcr.io/${{ github.repository }}
          subject-digest: ${{ steps.build.outputs.digest }}
          push-to-registry: true

      # Pillar 3: Cosign Signing
      - uses: sigstore/cosign-installer@v3
      - name: Sign image
        run: |
          cosign sign \
            --certificate-identity-regexp "https://github.com/${{ github.repository }}" \
            --certificate-oidc-issuer https://token.actions.githubusercontent.com \
            ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

Developer Takeaways

  • Start with SBOM today: Syft or Trivy โ€” adding it to your CI pipeline takes 5 minutes. Knowing what you're running is step one.
  • SLSA Level 2 is low-hanging fruit: If you use GitHub Actions, attest-build-provenance is built-in. One extra step.
  • Cosign for all production deployments: Sign every image before pushing to your registry. Verify before deploying.
  • Enforce at the last mile: Use Kyverno or OPA to block unsigned images, images without SBOMs, or images without provenance.
  • Regulations are coming: Even if you don't sell to the US government, enterprise customers will soon demand these. Getting ahead is always cheaper than catching up.

Conclusion

Supply chain security isn't something you do once and forget. It's a continuous layer of protection โ€” from git push to the moment your container runs in production. SBOM gives you visibility, SLSA gives you trust, and Cosign gives you integrity verification.

All three tools are free, open source, and can be integrated into your existing CI/CD pipeline in hours โ€” not weeks. Start with your team's most critical repository, deploy a pipeline like the one above, and see what happens.

Have you implemented supply chain security for your production workloads yet? If not, what's stopping you?


This post was written with AI assistance (Amy ๐ŸŒธ). Content has been reviewed by the author.

Related Posts