Skip to main content
← All Articles Β· Β· 11 min read

Software Supply Chain Security: SBOM, SLSA, and Sigstore Guide 2026

Comprehensive guide to software supply chain security in 2026. Learn how to generate SBOMs with Syft and Trivy, implement SLSA provenance, sign containers with Sigstore Cosign, and harden your GitHub Actions pipeline against supply chain attacks.

securitysupply-chainsbomslsasigstoredevopsdevsecops

Software Supply Chain Security: SBOM, SLSA, and Sigstore Guide 2026

On December 13, 2020, security researchers discovered that SolarWinds’ build system had been compromised for nine months. Attackers had injected malicious code directly into legitimate software builds, which were then signed and distributed to 18,000 customers β€” including the US Treasury, Pentagon, and hundreds of Fortune 500 companies.

The SolarWinds attack was a watershed moment for software supply chain security. It demonstrated that the build and distribution pipeline itself β€” not just the application code β€” is an attack surface. Since then, Log4Shell showed how transitive dependencies could expose millions of applications, and the XZ Utils backdoor in 2024 revealed how patient, long-term supply chain infiltration can target critical open-source infrastructure.

This guide covers the practical tools and frameworks developers can use to defend their software supply chains in 2026.


Understanding Supply Chain Attacks

Before diving into defenses, it helps to understand the attack patterns:

Build system compromise (SolarWinds) β€” Attackers gain access to CI/CD infrastructure and inject malicious code before signing. The resulting artifacts are indistinguishable from legitimate builds.

Dependency confusion β€” Attackers publish malicious packages to public registries (npm, PyPI) with names that shadow internal package names. Package managers fetch the public version instead.

Typosquatting β€” Publishing packages with names similar to popular libraries (reqeusts instead of requests, lodahs instead of lodash).

Account takeover β€” Compromising the npm/PyPI account of a popular package maintainer and publishing a malicious version.

Long-term infiltration (XZ Utils) β€” A bad actor contributes legitimate code for years to build trust, then introduces a backdoor. The XZ Utils backdoor (CVE-2024-3094) targeted SSH authentication on Linux systems and was caught by accident days before widespread distribution.

Transitive dependency attacks β€” Compromising a small, obscure package that is depended upon by thousands of larger packages. Log4Shell affected any Java application using log4j, including applications whose authors had no idea they were using it.

The common thread: you cannot secure what you cannot see. Understanding what is in your software is the foundation of supply chain security.


SBOM: Software Bill of Materials

What Is an SBOM?

A Software Bill of Materials (SBOM) is a machine-readable inventory of every component in a software artifact β€” libraries, frameworks, operating system packages, and their versions, licenses, and known vulnerabilities. Think of it as an ingredient label for software.

The Biden Executive Order on cybersecurity (2021) mandated SBOMs for software sold to the US federal government, which accelerated adoption across the industry. In 2026, SBOMs are increasingly expected in enterprise procurement.

What an SBOM tells you:

  • Every direct and transitive dependency
  • Version numbers and checksums
  • License information
  • Known CVEs at time of generation
  • Supplier information

SBOM Formats: SPDX vs CycloneDX

Two formats dominate the SBOM ecosystem:

SPDX (Software Package Data Exchange)

  • ISO/IEC 5962:2021 standard
  • Originally designed for license compliance
  • Supported formats: JSON, YAML, RDF, tag-value text
  • Better for license analysis workflows

CycloneDX

  • OWASP project, purpose-built for security use cases
  • Richer vulnerability and component relationship data
  • Better tooling ecosystem for DevSecOps
  • Supports VEX (Vulnerability Exploitability eXchange) for false-positive reduction

For most DevSecOps use cases, CycloneDX is the better choice due to its security-first design and superior tooling.

Generating SBOMs with Syft

Syft from Anchore is the most widely used SBOM generator. It supports container images, filesystems, archives, and OCI artifacts.

# Install Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

# Generate SBOM for a container image (CycloneDX format)
syft nginx:latest -o cyclonedx-json > nginx-sbom.json

# Generate SBOM for a directory
syft dir:./my-app -o spdx-json > my-app-sbom.spdx.json

# Generate SBOM for a specific language ecosystem
syft dir:./my-node-app -o cyclonedx-json \
  --select-catalogers "+javascript-package-cataloger"

# Scan and output multiple formats simultaneously
syft my-image:latest \
  -o cyclonedx-json=sbom.cyclonedx.json \
  -o spdx-json=sbom.spdx.json \
  -o table

Scanning SBOMs for Vulnerabilities with Grype

Syft pairs with Grype for vulnerability scanning:

# Install Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

# Scan a container image directly
grype nginx:latest

# Scan using an existing SBOM (faster, offline capable)
grype sbom:./nginx-sbom.json

# Fail CI if any Critical or High vulnerabilities found
grype nginx:latest --fail-on critical

# Output as JSON for processing
grype nginx:latest -o json > vulnerability-report.json

Generating SBOMs with Trivy

Trivy from Aqua Security is an all-in-one scanner that handles SBOM generation, vulnerability scanning, misconfigurations, and secrets detection.

# Install Trivy
brew install trivy  # macOS
# Or
wget https://github.com/aquasecurity/trivy/releases/latest/download/trivy_Linux_64bit.tar.gz

# Generate CycloneDX SBOM
trivy image --format cyclonedx --output sbom.json nginx:latest

# Generate SPDX SBOM
trivy image --format spdx-json --output sbom.spdx.json nginx:latest

# Scan filesystem for vulnerabilities and generate SBOM simultaneously
trivy fs \
  --format cyclonedx \
  --output sbom.json \
  --scanners vuln,secret,misconfig \
  ./my-app

# Scan with severity filtering
trivy image --severity HIGH,CRITICAL nginx:latest

# Generate SBOM in GitHub Actions
trivy image \
  --format sarif \
  --output trivy-results.sarif \
  my-registry/my-app:${{ github.sha }}

SLSA Framework: Supply-chain Levels for Software Artifacts

SLSA (pronounced β€œsalsa”) is a security framework from Google that defines four levels of supply chain integrity. Each level builds on the previous with increasingly strict requirements.

The Four SLSA Levels

SLSA Level 1 β€” Documented build process

  • Build process is scripted/automated (not manual)
  • Provenance (build metadata) is available
  • Minimum viable supply chain security

SLSA Level 2 β€” Build service

  • Uses a hosted CI/CD build service
  • Provenance is generated and signed by the build service
  • Source is version controlled

SLSA Level 3 β€” Hardened build

  • Build runs on a dedicated, ephemeral build environment
  • Build instructions are controlled by the source repository (not build system)
  • Provenance is non-falsifiable β€” the build service signs it, not the developer
  • All external build parameters are captured in provenance

SLSA Level 4 (deprecated in v1.0, replaced by SLSA v1.0 Build L3)

  • Two-party review for all changes
  • Hermetic builds (no network access during build)
  • Reproducible builds

Most organizations should target SLSA Level 2 initially, with L3 for critical artifacts.

Generating SLSA Provenance with GitHub Actions

The SLSA GitHub Actions generator creates signed provenance that meets SLSA Level 3:

# .github/workflows/release.yml
name: Release with SLSA Provenance

on:
  release:
    types: [created]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      hashes: ${{ steps.hash.outputs.hashes }}
    steps:
      - uses: actions/checkout@v4

      - name: Build artifacts
        run: |
          make build
          # Create checksums
          sha256sum dist/* > checksums.txt

      - name: Generate artifact hashes
        id: hash
        run: |
          echo "hashes=$(sha256sum dist/* | base64 -w0)" >> "$GITHUB_OUTPUT"

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: |
            dist/
            checksums.txt

  # Generate SLSA L3 provenance
  provenance:
    needs: [build]
    permissions:
      actions: read
      id-token: write
      contents: write
    uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
    with:
      base64-subjects: "${{ needs.build.outputs.hashes }}"
      upload-assets: true

Verifying SLSA Provenance

# Install slsa-verifier
go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest

# Verify a downloaded artifact
slsa-verifier verify-artifact \
  my-binary \
  --provenance-path my-binary.intoto.jsonl \
  --source-uri github.com/my-org/my-repo \
  --source-tag v1.2.3

Sigstore: Keyless Code Signing

Sigstore is an open-source project (backed by Google, Red Hat, and Purdue University) that makes cryptographic signing of software artifacts easy enough for everyone to use. It addresses a fundamental problem: traditional code signing requires managing long-lived private keys, which are themselves a supply chain risk.

Sigstore’s solution is keyless signing: instead of a persistent private key, developers use short-lived certificates issued against their OIDC identity (GitHub Actions OIDC, Google, Microsoft). The certificate binds the signature to the workflow run, not to a static key.

Cosign: Container Image Signing

Cosign signs and verifies container images and other OCI artifacts.

# Install Cosign
brew install cosign  # macOS
# Or download from GitHub releases

# Keyless signing in GitHub Actions (uses OIDC automatically)
cosign sign \
  --yes \
  my-registry/my-image:latest

# Verify a signed image
cosign verify \
  --certificate-identity-regexp="https://github.com/my-org/my-repo" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
  my-registry/my-image:latest

# Sign with a key file (for non-OIDC environments)
cosign generate-key-pair
cosign sign --key cosign.key my-registry/my-image:latest
cosign verify --key cosign.pub my-registry/my-image:latest

# Attach an SBOM to a signed image
cosign attach sbom --sbom sbom.json my-registry/my-image:latest
cosign sign --attachment sbom my-registry/my-image:latest

Rekor: Transparency Log

Rekor is Sigstore’s immutable, append-only transparency log. Every signature created through Sigstore is recorded in Rekor, providing public auditability β€” anyone can verify that a signature was made at a specific time by a specific identity.

# Install Rekor CLI
go install github.com/sigstore/rekor/cmd/rekor-cli@latest

# Search for entries by email
rekor-cli search --email [email protected]

# Get details about a specific entry
rekor-cli get --uuid <entry-uuid> --format json

# Verify a file was logged in Rekor
rekor-cli verify \
  --artifact my-binary \
  --signature my-binary.sig \
  --public-key my-key.pub

Fulcio: Certificate Authority

Fulcio is Sigstore’s CA that issues short-lived certificates tied to OIDC identities. When you do a keyless signing with Cosign, Fulcio:

  1. Receives your OIDC token (from GitHub, Google, Microsoft, etc.)
  2. Verifies the OIDC token with the identity provider
  3. Issues a short-lived X.509 certificate binding your identity to a public key
  4. The certificate expires in 10 minutes (so even if leaked, it’s useless)

You don’t interact with Fulcio directly β€” Cosign handles it automatically during keyless signing.


GitHub Actions Supply Chain Hardening

GitHub Actions workflows are a prime supply chain attack target. Compromising a popular action can affect thousands of repositories.

Pin Actions to Commit SHA

# Bad β€” mutable tag, can be changed by attacker
- uses: actions/checkout@v4

# Good β€” pinned to immutable SHA
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

Use Dependabot to automatically update pinned SHAs:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      actions:
        patterns:
          - "*"

Minimal Workflow Permissions

# Set restrictive default permissions
permissions: read-all

jobs:
  build:
    permissions:
      contents: read
      packages: write      # Only if publishing to GHCR
      id-token: write      # Only if using OIDC

Dependency Review Action

# .github/workflows/dependency-review.yml
name: Dependency Review

on:
  pull_request:
    branches: [main]

permissions:
  contents: read
  pull-requests: write

jobs:
  dependency-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

      - name: Dependency Review
        uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a
        with:
          fail-on-severity: high
          deny-licenses: GPL-2.0, AGPL-3.0
          comment-summary-in-pr: true

Full CI Pipeline with Supply Chain Controls

# .github/workflows/secure-build.yml
name: Secure Build and Release

on:
  push:
    tags: ['v*']

permissions:
  contents: read

jobs:
  build-and-sign:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
      id-token: write      # For Cosign keyless signing
      security-events: write  # For SARIF upload

    steps:
      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

      - name: Install Cosign
        uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da

      - name: Install Syft
        uses: anchore/sbom-action/download-syft@v0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push image
        id: build
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
          sbom: true       # Docker BuildKit generates SBOM
          provenance: true  # Include SLSA provenance

      - name: Sign image with Cosign (keyless)
        run: |
          cosign sign --yes \
            ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

      - name: Generate SBOM with Syft
        run: |
          syft ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }} \
            -o cyclonedx-json=sbom.cyclonedx.json

      - name: Attach and sign SBOM
        run: |
          cosign attach sbom \
            --sbom sbom.cyclonedx.json \
            ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
          cosign sign --yes --attachment sbom \
            ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

      - name: Scan for vulnerabilities
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
          format: sarif
          output: trivy-results.sarif
          severity: HIGH,CRITICAL
          exit-code: 1

      - name: Upload Trivy results to Security tab
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: trivy-results.sarif

Dependency Pinning

Python: pip-compile and hash pinning

# Install pip-tools
pip install pip-tools

# Compile requirements with hashes
pip-compile --generate-hashes requirements.in > requirements.txt

The generated requirements.txt looks like:

requests==2.31.0 \
    --hash=sha256:58cd2187423d8... \
    --hash=sha256:942c5a758f98d...
certifi==2023.7.22 \
    --hash=sha256:539cc1d13202e6... \
    --hash=sha256:92ed7d8...
# Install with hash verification
pip install --require-hashes -r requirements.txt

Node.js: lockfile integrity

# Use npm ci instead of npm install in CI β€” enforces lockfile
npm ci

# Audit dependencies
npm audit --audit-level=high

# Or use socket.dev for advanced supply chain analysis
npx @socket/npm-audit-report

Go: module verification

# Go modules are pinned by default via go.sum
# Verify module checksums against the Go checksum database
go mod verify

# Use GONOSUMCHECK and GONOSUMDB carefully β€” these bypass verification
# Never set GONOSUMCHECK=* in production

Implementing a Practical Supply Chain Security Baseline

Here is a prioritized checklist for teams starting their supply chain security program:

Week 1-2: Visibility

  • Generate SBOMs for all production container images using Syft or Trivy
  • Integrate vulnerability scanning into CI/CD with trivy or grype
  • Enable Dependabot or Renovate for automated dependency updates

Week 3-4: Hardening

  • Pin all GitHub Actions to commit SHAs
  • Set minimal workflow permissions (permissions: read-all as default)
  • Enable branch protection and require code review for all merges
  • Add the Dependency Review Action to all PR workflows

Month 2: Signing

  • Implement Cosign keyless signing for all published container images
  • Attach SBOMs to signed images
  • Add SBOM attestations to release artifacts

Month 3: Provenance

  • Adopt the SLSA GitHub Actions generator to reach SLSA Level 3
  • Implement SBOM-based license compliance checks in CI
  • Set up continuous vulnerability monitoring (Grype, Trivy) on production images

Ongoing

  • Review and rotate external secrets quarterly
  • Subscribe to security advisories for critical dependencies (GitHub Security Advisories, OSV)
  • Conduct supply chain threat modeling annually

Key Tools Reference

ToolPurposeMaintained By
SyftSBOM generationAnchore
GrypeVulnerability scanning from SBOMAnchore
TrivyAll-in-one scanner + SBOMAqua Security
CosignContainer image signingSigstore / OpenSSF
RekorSignature transparency logSigstore / OpenSSF
FulcioShort-lived certificate CASigstore / OpenSSF
slsa-verifierSLSA provenance verificationSLSA Framework
in-totoSupply chain metadata frameworkin-toto
SocketAdvanced npm/PyPI threat detectionSocket.dev

Conclusion

Software supply chain security has moved from a niche concern to a mainstream requirement, driven by high-profile attacks and regulatory pressure. The good news is that the tooling in 2026 has matured dramatically β€” Syft, Trivy, Cosign, and the SLSA framework are all production-ready and free to use.

The most important first step is visibility: generate SBOMs for your artifacts. You cannot defend against Log4Shell-style transitive dependency vulnerabilities if you do not know which version of log4j is buried four layers deep in your dependency tree. Once you can see what is in your software, you can systematically scan for vulnerabilities, sign your artifacts to prove provenance, and implement CI/CD controls that make it hard to slip malicious code into your build pipeline.

Start with SBOM generation and vulnerability scanning. Add signing with Cosign. Harden your CI/CD workflows by pinning action versions and minimizing permissions. These three steps alone put you dramatically ahead of most organizations β€” and ahead of most of the attack patterns that supply chain adversaries actually use.

Free Download

50 CLI Commands That Save Hours Every Week

The exact Git shortcuts, file search tricks, Docker commands, and productivity hacks that senior developers use daily. Compiled from 5+ years of shipping production code.

  • Git mastery (10 cmds)
  • File & search wizardry
  • Docker & DevOps tricks
  • Process & network tools
  • Productivity boosters
  • macOS & Linux install guide

No spam. 1 email/week max. Unsubscribe anytime.

Found this guide useful? Check out our free developer tools.