Container Security & Supply Chain 2026 — SBOM, Cosign, SLSA, Trivy for DevSecOps

Posted on: 4/21/2026 11:15:15 PM

In 2026, containers are no longer just a packaging mechanism — they are the core deployment unit of every production system. But alongside their ubiquity, software supply chain attacks have surged 742% over the past 3 years. From the SolarWinds incident to typosquatting attacks on npm/PyPI, the risk is no longer in the code you write — but in the code you pull in.

742%Supply chain attack growth (2022–2025)
23Advisory sources aggregated by Docker Scout
09/2026EU Cyber Resilience Act mandates SBOM
L3Highest SLSA Level — hardened build

This article dives deep into the 4 pillars of modern container security: SBOM (know what you're running), Image Signing (trust the origin), SLSA (verify the build process), and Vulnerability Scanning (catch flaws early). Together they form an end-to-end DevSecOps pipeline.

1. The Big Picture — Why Supply Chain Security Became Priority #1

Before 2020, container security mostly meant periodic CVE scanning. But a series of incidents changed the landscape:

12/2020
SolarWinds Sunburst — malware injected into the build pipeline, affecting 18,000 organizations including US government agencies. This was the moment the industry realized: build systems need protection too.
01/2022
Log4Shell (CVE-2021-44228) — a vulnerability in Log4j affecting millions of Java applications. Most organizations spent weeks just answering "are we using Log4j?" → SBOM became an urgent need.
05/2024
xz-utils backdoor (CVE-2024-3094) — a maintainer planted a backdoor in a widely-used compression library, nearly making it into every Linux distribution. Proof that even trusted open-source can be compromised.
09/2026
EU Cyber Resilience Act (CRA) takes effect — mandating SBOM, vulnerability handling processes, and coordinated disclosure for all software sold in the EU.

⚠ A Sobering Reality

According to Sonatype research, 96% of vulnerable open-source packages already have a patched version available — but developers don't update. Supply chain security isn't just about tools, it's about culture and process.

2. SBOM — Software Bill of Materials: Know Exactly What You're Running

An SBOM is a complete inventory of every component inside a container image — from base OS packages and language-specific dependencies to transitive dependencies you never directly declared.

2.1 Why SBOMs Matter

When Log4Shell hit, organizations with SBOMs answered "are we affected?" in minutes. Those without took weeks to manually audit. SBOMs transform reactive incident response into proactive risk management.

CriteriaSPDX (Linux Foundation)CycloneDX (OWASP)
StandardISO/IEC 5962:2021ECMA-424, OWASP standard
FocusLicense compliance + securitySecurity-first, built-in VEX
FormatsJSON, XML, RDF, Tag-ValueJSON, XML, Protobuf
ToolingBroader (longer history)More modern, includes VDR/VEX
Best forCompliance, license auditsDevSecOps, vulnerability mgmt

2.3 Generating SBOMs with Trivy

Trivy (by Aqua Security) is the most versatile scanner available — it scans vulnerabilities, generates SBOMs, and checks misconfigurations. The latest version (v0.69+) supports concurrent DB access for parallel CI pipelines.

# Generate CycloneDX SBOM for a .NET image
trivy image --format cyclonedx --output sbom.json myapp:latest

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

# Scan from an existing SBOM (no need to pull image again)
trivy sbom sbom.json

✅ Best Practice: SBOM at Build Time

Always generate SBOMs at build time (in CI/CD pipeline), NOT after deployment. SBOMs created from build inputs are more accurate than those reverse-engineered from built images, since they have complete dependency resolution information.

2.4 Docker Scout — Native SBOM in Docker

Docker Scout integrates directly into Docker Desktop and Docker Hub, aggregating data from 23 advisory sources including NVD, GitHub Advisory Database, and vendor-specific feeds. Its biggest advantage is Package URL (PURL) matching which significantly reduces false positives.

# Analyze image directly in Docker CLI
docker scout cves myapp:latest

# Generate SBOM
docker scout sbom myapp:latest --format cyclonedx --output sbom.json

# Compare two image versions
docker scout compare myapp:v2 --to myapp:v1

3. Image Signing with Sigstore/Cosign — Verify Container Origins

SBOMs tell you what's inside a container, but who ensures the image you pull is actually the one built by a trusted CI/CD pipeline? This is the problem image signing solves.

3.1 Sigstore — Signing Infrastructure for Open Source

Sigstore is an OpenSSF (Open Source Security Foundation) project with 3 core components:

graph TD
    A[Developer / CI Pipeline] -->|Request certificate| B[Fulcio
Certificate Authority] B -->|Short-lived cert
OIDC-verified| A A -->|Sign artifact| C[Container Registry
OCI Artifact] A -->|Record signature| D[Rekor
Transparency Log] E[Consumer / K8s] -->|Verify signature| C E -->|Check transparency log| D style A fill:#e94560,stroke:#fff,color:#fff style B fill:#2c3e50,stroke:#fff,color:#fff style C fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style D fill:#2c3e50,stroke:#fff,color:#fff style E fill:#4CAF50,stroke:#fff,color:#fff

Sigstore architecture: Fulcio issues certificates, Rekor provides transparency, Consumers verify

  • Fulcio — A free Certificate Authority that issues short-lived certificates (typically 10 minutes) based on OIDC identity (GitHub, Google, Microsoft).
  • Rekor — A public transparency log recording every signing event so anyone can audit.
  • Cosign — CLI tool for signing and verifying container images, SBOMs, and other OCI artifacts.

3.2 Keyless Signing — No Key Management Required

Traditional approaches require creating key pairs, protecting private keys, and rotating them periodically — complex and risky if a key leaks. Keyless signing in Cosign v3 eliminates this entirely:

# Sign image — Cosign automatically uses OIDC identity from GitHub Actions
cosign sign ghcr.io/myorg/myapp:v2.1.0

# Verify image — check identity + OIDC issuer
cosign verify ghcr.io/myorg/myapp:v2.1.0 \
  --certificate-identity=https://github.com/myorg/myapp/.github/workflows/build.yml@refs/heads/main \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com

# Sign with SBOM attestation
cosign attest --predicate sbom.json --type cyclonedx ghcr.io/myorg/myapp:v2.1.0

How Keyless Signing Works

1) CI job authenticates with OIDC provider (GitHub Actions) → 2) Fulcio verifies the OIDC token and issues a short-lived certificate containing identity claims → 3) Cosign signs the image using this certificate → 4) The signature + certificate are recorded in the Rekor transparency log → 5) The ephemeral private key is immediately destroyed. Result: cryptographic proof without ever holding a private key.

3.3 Verification in Kubernetes with Policy Controller

Image signing only matters when your Kubernetes cluster enforces verification. Sigstore Policy Controller (or Kyverno/OPA Gatekeeper) blocks unsigned images:

# Kyverno ClusterPolicy — only allow images signed by CI pipeline
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-cosign-signature
      match:
        any:
          - resources:
              kinds: ["Pod"]
      verifyImages:
        - imageReferences: ["ghcr.io/myorg/*"]
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/myorg/*"
                    issuer: "https://token.actions.githubusercontent.com"
                    rekor:
                      url: https://rekor.sigstore.dev

4. SLSA Framework — Supply-chain Levels for Software Artifacts

SLSA (pronounced "salsa") is a framework from Google/OpenSSF defining 4 security levels for build pipelines. Its goal: ensure the artifact you deploy is genuinely the one created from reviewed source code.

4.1 The Four SLSA Build Levels

graph LR
    L0[L0
No provenance] --> L1[L1
Provenance exists] L1 --> L2[L2
Hosted build
Signed provenance] L2 --> L3[L3
Hardened build
Isolated environment] style L0 fill:#f8f9fa,stroke:#e0e0e0,color:#888 style L1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style L2 fill:#e94560,stroke:#fff,color:#fff style L3 fill:#2c3e50,stroke:#fff,color:#fff

SLSA Build Track: from L0 (nothing) to L3 (hardened, isolated build)

LevelRequirementsProtects AgainstExample
L0No provenanceNothingBuilding on a developer machine
L1Provenance auto-generatedUnintentional driftGitHub Actions logging builds
L2Hosted build + Signed provenanceProvenance forgeryGitHub Actions + SLSA generator
L3Isolated build environment, no reuseCompromised build systemEphemeral container runners

4.2 Achieving SLSA L3 with GitHub Actions

GitHub Actions provides an official SLSA Container Generator that lets you achieve SLSA L3 without building your own infrastructure:

# .github/workflows/release.yml
name: Build and Push with SLSA Provenance
on:
  push:
    tags: ['v*']

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4

      - name: Build and push
        id: build
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/myorg/myapp:${{ github.ref_name }}

  provenance:
    needs: build
    permissions:
      actions: read
      id-token: write
      packages: write
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
    with:
      image: ghcr.io/myorg/myapp
      digest: ${{ needs.build.outputs.digest }}
      registry-username: ${{ github.actor }}
    secrets:
      registry-password: ${{ secrets.GITHUB_TOKEN }}

✅ SLSA Level 2 Is the Practical Target for Most Teams

SLSA L3 requires ephemeral, isolated build environments — which GitHub Actions hosted runners already provide. However, if you use self-hosted runners, ensure they are ephemeral (created fresh per job, never reused). Most teams should start at L2 and progressively move to L3.

5. Vulnerability Scanning — Catch Flaws Before They Reach Production

ToolTypeSBOMLicenseKey Strength
TrivyMulti-purpose✅ CycloneDX, SPDXApache 2.0Scans images, filesystems, IaC, K8s configs. Fastest OSS scanner
Docker ScoutDocker-native✅ CycloneDX, SPDXProprietary (free tier)23 advisory sources, PURL matching, Docker Desktop integration
GrypeVulnerability✅ (via Syft)Apache 2.0Lightweight, fast, pairs with Syft for SBOM. By Anchore
Snyk ContainerCommercialProprietary (free tier)Base image recommendations, automated fix PRs

5.2 Practical Pipeline Scanning with Trivy in GitHub Actions

# Scan in CI — fail build on HIGH/CRITICAL
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: ghcr.io/myorg/myapp:${{ github.sha }}
    format: 'sarif'
    output: 'trivy-results.sarif'
    severity: 'HIGH,CRITICAL'
    exit-code: '1'  # Fail pipeline on findings

- name: Upload Trivy scan results to GitHub Security
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: 'trivy-results.sarif'

⚠ Don't Just Scan — Act on It

The most common mistake: running scanners in CI but only generating reports without failing the build. If you don't block deployment on HIGH/CRITICAL CVEs, the scanner is just decoration. Set exit-code: 1 and handle false positives via a .trivyignore file.

5.3 Scanning .NET Container Images Effectively

For .NET, best practice is to use chiseled images (Ubuntu distroless) to reduce the attack surface before scanning:

# Multi-stage build — .NET 10 chiseled image
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app --no-restore

FROM mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled AS runtime
WORKDIR /app
COPY --from=build /app .

# Non-root user (chiseled images default to non-root)
USER $APP_UID
ENTRYPOINT ["dotnet", "MyApp.dll"]
# Compare CVE counts between standard and chiseled images
trivy image mcr.microsoft.com/dotnet/aspnet:10.0         # ~50-80 CVEs
trivy image mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled  # ~5-10 CVEs

6. End-to-End DevSecOps Pipeline — Putting It All Together

Here's the complete pipeline architecture combining all 4 pillars:

graph TD
    A[Source Code
GitHub] -->|Push / PR| B[Build
docker build] B --> C[SBOM Generation
Trivy / Syft] B --> D[Vulnerability Scan
Trivy + Docker Scout] D -->|CRITICAL found?| E{Gate} E -->|Yes| F[❌ Block Deploy] E -->|No| G[Image Signing
Cosign keyless] C --> G G --> H[Push to Registry
+ SBOM attestation] H --> I[SLSA Provenance
L3 Generator] I --> J[Deploy to K8s] J --> K[Admission Control
Kyverno verify] K -->|Signature valid?| L{Gate} L -->|Yes| M[✅ Pod Running] L -->|No| N[❌ Rejected] style A fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style B fill:#2c3e50,stroke:#fff,color:#fff style G fill:#e94560,stroke:#fff,color:#fff style I fill:#e94560,stroke:#fff,color:#fff style K fill:#4CAF50,stroke:#fff,color:#fff style M fill:#4CAF50,stroke:#fff,color:#fff style F fill:#ff9800,stroke:#fff,color:#fff style N fill:#ff9800,stroke:#fff,color:#fff

End-to-end DevSecOps pipeline: Build → Scan → Sign → Provenance → Verify → Deploy

6.1 Complete GitHub Actions Workflow

name: Secure Container Pipeline
on:
  push:
    branches: [main]

permissions:
  contents: read
  packages: write
  id-token: write
  security-events: write

env:
  IMAGE: ghcr.io/${{ github.repository }}

jobs:
  build-scan-sign:
    runs-on: ubuntu-latest
    outputs:
      digest: ${{ steps.push.outputs.digest }}
    steps:
      - uses: actions/checkout@v4

      # 1. Build image
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        id: push
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ${{ env.IMAGE }}:${{ github.sha }}

      # 2. Generate SBOM
      - name: Generate SBOM
        run: |
          trivy image --format cyclonedx \
            --output sbom.cdx.json \
            ${{ env.IMAGE }}:${{ github.sha }}

      # 3. Vulnerability scan — fail on HIGH/CRITICAL
      - name: Scan vulnerabilities
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ${{ env.IMAGE }}:${{ github.sha }}
          severity: 'HIGH,CRITICAL'
          exit-code: '1'
          format: 'sarif'
          output: 'trivy.sarif'

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: trivy.sarif

      # 4. Sign image (keyless via GitHub OIDC)
      - uses: sigstore/cosign-installer@v3
      - name: Sign image
        run: cosign sign --yes ${{ env.IMAGE }}@${{ steps.push.outputs.digest }}

      # 5. Attach SBOM attestation
      - name: Attest SBOM
        run: |
          cosign attest --yes \
            --predicate sbom.cdx.json \
            --type cyclonedx \
            ${{ env.IMAGE }}@${{ steps.push.outputs.digest }}

  # 6. SLSA L3 provenance
  provenance:
    needs: build-scan-sign
    permissions:
      actions: read
      id-token: write
      packages: write
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
    with:
      image: ${{ needs.build-scan-sign.outputs.image }}
      digest: ${{ needs.build-scan-sign.outputs.digest }}
      registry-username: ${{ github.actor }}
    secrets:
      registry-password: ${{ secrets.GITHUB_TOKEN }}

7. Continuous Monitoring — Security Doesn't Stop at CI/CD

New vulnerabilities appear daily. An image that's "clean" today might have a CRITICAL CVE next week. Continuous monitoring is essential:

7.1 Registry-level Scanning

  • GitHub Container Registry — integrates Dependabot alerts for container images
  • AWS ECR — Enhanced scanning with Amazon Inspector, auto-scan on push with periodic rescans
  • Azure ACR — Microsoft Defender for Containers continuous scanning
  • Docker Hub — Docker Scout monitoring dashboard

7.2 Runtime Scanning in Kubernetes

# Trivy Operator — continuously scan all workloads in the cluster
helm install trivy-operator aquasecurity/trivy-operator \
  --namespace trivy-system --create-namespace \
  --set trivy.severity="HIGH,CRITICAL" \
  --set operator.scanJobTimeout=10m

# View vulnerability reports
kubectl get vulnerabilityreports -A -o wide

8. Implementation Checklist for Teams

Here's a practical roadmap for adopting supply chain security from zero:

WeekActionToolSLSA Level
1-2Switch to chiseled/distroless base imagesDocker multi-stage build
3-4Add vulnerability scanning to CI, fail on CRITICALTrivy + GitHub ActionsL0 → L1
5-6Generate SBOMs at build time, store alongside imageTrivy / Syft / Docker ScoutL1
7-8Keyless image signing in CICosign + SigstoreL2
9-10SLSA provenance generationslsa-github-generatorL2 → L3
11-12Admission control in K8s — enforce signed imagesKyverno / Sigstore Policy ControllerL3

✅ Start Small, Scale Gradually

Don't try to implement everything at once. Start with vulnerability scanning (weeks 3-4) — it has the highest ROI. Once your team is comfortable fixing CVEs before deploying, add signing and provenance. Supply chain security is a marathon, not a sprint.

9. Conclusion

Container supply chain security in 2026 is no longer "nice-to-have" — with the EU Cyber Resilience Act mandating SBOMs from September 2026 and the relentless rise of supply chain attacks, it's a hard requirement. The good news is the tooling ecosystem is mature: Trivy for scanning + SBOM, Cosign for keyless signing, SLSA for build provenance — all open-source, free, and well-integrated with GitHub Actions.

The right strategy is defense-in-depth: don't rely on a single layer of protection, but combine multiple layers (scan → sign → provenance → admission control) so that even if one layer is bypassed, the others still catch threats.

References:
SLSA — Supply-chain Levels for Software Artifacts · Sigstore Documentation · Trivy by Aqua Security · Docker Scout Documentation · Aqua Security — Supply Chain Security with Trivy · Cosign — GitHub · Chainguard — How to Sign a Container with Cosign · OpenSSF — Open Source Security Foundation