DevOps

Securing Your Software Supply Chain: SBOMs & Sigstore

Dive deep into software supply chain security. Understand SBOMs (Software Bill of Materials) for transparency and Sigstore for verifiable software integrity, with practical examples and architecture.

Khader Vali August 26, 2026 16 min read

Securing Your Software Supply Chain: SBOMs & Sigstore Explained

In the digital age, software powers everything. From the operating systems on our phones to the critical infrastructure that keeps our world running, software is ubiquitous. But with this omnipresence comes a growing attack surface – the software supply chain. Recent years have seen a dramatic increase in sophisticated supply chain attacks, from the notorious SolarWinds compromise to the widespread impact of vulnerabilities like Log4j. These incidents have highlighted a critical gap in how we build, distribute, and consume software: a lack of transparency and verifiable trust.

As a senior software engineer, I’ve seen firsthand the shift from perimeter-based security to a more holistic, zero-trust approach. Part of this evolution involves understanding and securing every link in our software supply chain. This article will demystify two cornerstone technologies that are rapidly becoming indispensable in this fight: Software Bill of Materials (SBOMs) and Sigstore. We’ll explore what they are, why they matter, how they work, and most importantly, how they can be leveraged together to build a more resilient and secure software ecosystem.

By the end of this deep dive, you’ll have a solid understanding of:

  • The inherent risks within the software supply chain.
  • How SBOMs provide critical transparency into software components.
  • How Sigstore establishes verifiable trust and integrity for software artifacts.
  • Practical ways to integrate these technologies into your development and deployment workflows.
  • The synergy between SBOMs and Sigstore in fortifying your defenses.

Understanding the Software Supply Chain: A Complex Ecosystem

Before we can secure it, we must first understand it. The “software supply chain” refers to the entire lifecycle of software, from its conception to its deployment and ongoing maintenance. It’s a vast and intricate network of people, processes, and technologies. Think of it like a physical supply chain, but instead of raw materials and finished goods, we’re dealing with source code, dependencies, build tools, and executable binaries.

Components of the Software Supply Chain

Let’s break down the typical stages and components:

  1. Source Code Repositories: Where code lives (GitHub, GitLab, Bitbucket). This includes your own code, but also a myriad of open-source libraries and frameworks pulled in as dependencies.
  2. Developer Workstations: The environments where developers write, test, and debug code. Vulnerabilities here (e.g., compromised credentials, malicious IDE extensions) can be entry points.
  3. Package Managers & Registries: Tools like npm, pip, Maven, NuGet, Go modules, and their respective registries (npm registry, PyPI, Maven Central, Docker Hub, etc.). These are critical for managing dependencies, but also a common vector for injecting malicious packages.
  4. Build Systems: Compilers, linkers, build tools (e.g., Jenkins, GitHub Actions, GitLab CI/CD, Azure DevOps, CircleCI). These transform source code into deployable artifacts. A compromised build system can inject malware or alter binaries.
  5. Artifact Repositories: Centralized storage for built artifacts (e.g., Docker images, JAR files, NuGet packages). Examples include JFrog Artifactory, Nexus Repository Manager, AWS ECR, GCP Artifact Registry.
  6. Deployment & Orchestration Tools: Kubernetes, Helm, Ansible, Terraform, Spinnaker. These tools manage the deployment and scaling of applications, often pulling artifacts from repositories.
  7. Cloud Infrastructure & Runtimes: The underlying platforms where software executes (AWS, Azure, GCP, bare metal servers).

The Inherent Vulnerabilities

Each of these stages introduces potential vulnerabilities. Consider the following attack vectors:

  • Dependency Confusion/Typosquatting: Malicious packages with similar names to popular libraries, or private packages being pulled from public registries.
  • Compromised Developer Accounts: An attacker gaining access to a developer’s credentials can inject malicious code directly into a repository.
  • Malicious Code Injection: Inserting backdoors or malware into source code, build scripts, or deployment configurations.
  • Build System Tampering: Altering build processes to inject malicious code into final artifacts without changing the original source code.
  • Registry Compromise: An attacker pushing malicious versions of artifacts to a legitimate registry.
  • Weak Supply Chain Practices: Lack of signing, inadequate access controls, outdated dependencies, or insufficient vulnerability scanning.

The sheer complexity and interconnectedness of modern software development make securing the supply chain a daunting but essential task. It’s a chain, and its strength is determined by its weakest link. Our goal is to strengthen as many of those links as possible.

<

Securing Your Software Supply Chain: SBOMs & Sigstore
Generated Image

>

The Problem: Lack of Transparency and Trust

At the heart of many software supply chain vulnerabilities lies a fundamental problem: a lack of transparency and verifiable trust. When you download a library or deploy a container image, how do you truly know what’s inside it? How can you be certain it hasn’t been tampered with since it left the developer’s workstation or the build system?

Today, we often rely on implicit trust. We trust the maintainers of open-source projects, the security of public registries, and the integrity of our CI/CD pipelines. While this implicit trust has largely served us, the escalating sophistication of attacks demands explicit, verifiable trust.

The “Black Box” Dilemma

Most software artifacts today are “black boxes.” When you pull a Docker image, you see a collection of layers, but understanding the exact components, their versions, and their provenance (where they came from) is incredibly difficult without specialized tools. This opacity makes it challenging to:

  • Identify known vulnerabilities: If you don’t know you’re using a specific version of OpenSSL, how can you know if it’s affected by a CVE?
  • Comply with licenses: Ensuring all third-party components adhere to your organization’s licensing policies.
  • Perform audits: Tracing the origin and transformation of every byte of code in your production system.
  • Respond to incidents: When a new critical vulnerability emerges (like Log4j), quickly identifying all affected systems becomes a frantic, manual effort.

This lack of transparency is compounded by the challenge of verifying integrity. How can you be sure that the artifact you downloaded is exactly what the original developer intended, and that no malicious actor injected code or altered binaries along the way? Traditional signing mechanisms exist, but they often suffer from complex key management, scalability issues, and a lack of broad adoption.

Solution Part 1: Software Bill of Materials (SBOMs) for Transparency

Enter the Software Bill of Materials (SBOM). If the problem is a lack of transparency, the SBOM is the answer. An SBOM is essentially a formal, machine-readable inventory of all the components that make up a piece of software. Think of it like the ingredient list on a food product or the parts list for a complex machine.

What is an SBOM and Why Do We Need It?

An SBOM identifies the constituent components, their suppliers, versions, dependencies, and other critical metadata. It’s not just about direct dependencies; it’s about transitive dependencies too – the dependencies of your dependencies, and so on. This comprehensive view provides unprecedented visibility into the software supply chain.

The primary drivers for SBOM adoption are:

  • Vulnerability Management: The ability to quickly identify if your software contains a component affected by a newly disclosed vulnerability (e.g., Log4j, Heartbleed). This dramatically reduces response times during critical incidents.
  • License Compliance: Tracking open-source licenses to ensure compliance with legal obligations and organizational policies.
  • Risk Assessment: Understanding the origin and security posture of all components, allowing for better risk management decisions.
  • Supply Chain Security: Providing a baseline for verifying the integrity of software by comparing the deployed components against the expected SBOM.
  • Regulatory Requirements: Governments and industry bodies (e.g., U.S. Executive Order on Cybersecurity) are increasingly mandating SBOMs for critical software.

Key Components of an SBOM

While standards vary slightly, a typical SBOM includes information such as:

  • Component Name: The human-readable name of the software component (e.g., Apache Log4j, OpenSSL).
  • Component Version: The specific version identifier (e.g., 2.17.0, 1.1.1k).
  • Supplier: The entity that created or maintains the component (e.g., Apache Software Foundation, OpenSSL Project).
  • Unique Identifier (PURL, CPE, Package URL): A standardized way to identify a component across different systems.
  • Cryptographic Hash: A checksum (SHA256, MD5) of the component’s files, used to verify integrity.
  • Licenses: The licenses under which the component is distributed (e.g., Apache 2.0, MIT, GPL).
  • Relationships: How components relate to each other (e.g., ‘A depends on B’, ‘C contains D’).
  • Timestamp: When the SBOM was generated.

SBOM Standards: SPDX & CycloneDX

To ensure interoperability and machine readability, several open standards have emerged for SBOMs:

SPDX (Software Package Data Exchange)

Developed by the Linux Foundation, SPDX is one of the most mature and widely adopted SBOM formats. It’s designed to be comprehensive and flexible, capable of representing a broad range of information about software packages. SPDX documents can be expressed in various formats, including tag-value, RDF, XML, JSON, and YAML.

Example of an SPDX JSON snippet:

{
  "SPDXID": "SPDXRef-DOCUMENT",
  "spdxVersion": "SPDX-2.3",
  "dataLicense": "CC0-1.0",
  "name": "MyApplication-1.0-SBOM",
  "documentNamespace": "https://spdx.org/spdxdocs/MyApplication-1.0-SBOM-2023-10-27",
  "creationInfo": {
    "created": "2023-10-27T10:00:00Z",
    "creators": [
      "Tool: Syft-0.90.0",
      "Organization: Khadervali.com"
    ]
  },
  "packages": [
    {
      "SPDXID": "SPDXRef-Package-log4j-core-2.17.1",
      "name": "log4j-core",
      "versionInfo": "2.17.1",
      "description": "Apache Log4j Core Library",
      "downloadLocation": "NOASSERTION",
      "filesAnalyzed": false,
      "homepage": "https://logging.apache.org/log4j/2.x/",
      "licenseConcluded": "Apache-2.0",
      "licenseDeclared": "Apache-2.0",
      "supplier": "Organization: Apache Software Foundation",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE_MANAGER",
          "referenceLocator": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1",
          "referenceType": "purl"
        }
      ],
      "checksums": [
        {
          "algorithm": "SHA256",
          "checksumValue": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
        }
      ]
    }
  ],
  "relationships": [
    {
      "spdxElementId": "SPDXRef-DOCUMENT",
      "relationshipType": "DESCRIBES",
      "relatedSpdxElement": "SPDXRef-Package-log4j-core-2.17.1"
    }
  ]
}

CycloneDX

Maintained by the OWASP Foundation, CycloneDX is another popular, lightweight, and versatile SBOM standard. It focuses on security and supply chain use cases, making it particularly well-suited for vulnerability management and risk assessment. CycloneDX also supports JSON, XML, and Protobuf formats.

Example of a CycloneDX JSON snippet:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
  "version": 1,
  "metadata": {
    "timestamp": "2023-10-27T10:00:00Z",
    "tools": [
      {
        "vendor": "Anchore",
        "name": "Syft",
        "version": "0.90.0"
      }
    ],
    "component": {
      "type": "application",
      "name": "MyApplication",
      "version": "1.0"
    }
  },
  "components": [
    {
      "type": "library",
      "name": "log4j-core",
      "version": "2.17.1",
      "purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1",
      "hashes": [
        {
          "alg": "SHA256",
          "content": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
        }
      ],
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0"
          }
        }
      ]
    }
  ]
}

Both SPDX and CycloneDX are excellent choices, and many tools support generating both formats. The key is to choose one and consistently apply it across your organization.

Generating and Managing SBOMs

Manual SBOM generation is impractical. Fortunately, a robust ecosystem of tools exists to automate this process:

  • Syft (by Anchore): A powerful CLI tool that scans container images and filesystems to generate SBOMs in SPDX, CycloneDX, and other formats. It supports a wide range of programming languages and package managers.
  • Tern (by VMware): Another open-source tool that inspects container images to create SBOMs.
  • Grype (by Anchore): Often used in conjunction with Syft, Grype takes an SBOM and cross-references it against various public vulnerability databases (NVD, GitHub Advisories, etc.) to identify known CVEs.
  • Dependency-Track (by OWASP): A platform for continuous SBOM analysis and vulnerability management. It ingests SBOMs, correlates components with vulnerabilities, and provides a dashboard for tracking risk.
  • Snyk, Mend.io (formerly WhiteSource), Sonatype Nexus Lifecycle: Commercial solutions offering comprehensive software composition analysis (SCA) and SBOM generation.

Integrating SBOM Generation into CI/CD

The most effective way to leverage SBOMs is to integrate their generation directly into your CI/CD pipeline. Every time you build an artifact (e.g., a Docker image, a WAR file), an SBOM should be generated and associated with it. This ensures that your SBOMs are always up-to-date and reflect the exact state of your built software.

Here’s a simplified example of how you might integrate Syft into a CI/CD pipeline (e.g., GitHub Actions):

name: Generate SBOM and Scan

on:
  push:
    branches:
      - main

jobs:
  build-and-sbom:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Build Docker image
        run: docker build -t my-app:latest .

      - name: Generate SBOM (SPDX JSON)
        run: syft my-app:latest -o spdx-json > my-app-sbom.spdx.json
        # Store this SBOM securely, perhaps as a build artifact or push to a repository
        # For a real pipeline, you'd publish this to an artifact registry alongside the image

      - name: Scan SBOM for vulnerabilities with Grype
        run: grype sbom:my-app-sbom.spdx.json --scope all-layers --output cyclonedx-json > my-app-vulnerabilities.cyclonedx.json
        # You'd typically fail the build if critical vulnerabilities are found
        # For example: grype --fail-on high sbom:my-app-sbom.spdx.json

      - name: Upload SBOM as artifact
        uses: actions/upload-artifact@v3
        with:
          name: my-app-sbom
          path: my-app-sbom.spdx.json

Real-World Scenario: Responding to a Log4j-like Vulnerability with SBOMs

Imagine a new, critical vulnerability, “BadBug,” is discovered in a widely used Java logging library, similar to Log4j. Without SBOMs, your response would typically involve:

  1. Panic and frantic communication.
  2. Manually reviewing `pom.xml`, `build.gradle`, `package.json`, or `requirements.txt` files for all your applications.
  3. Running `grep` commands across repositories to find mentions of the affected library.
  4. Potentially deploying vulnerable software because you missed a transitive dependency.
  5. Days or weeks of effort to identify, patch, and verify all affected systems.

Now, consider the scenario with SBOMs in place:

  1. Upon disclosure of “BadBug” (CVE-XXXX-YYYY), you receive an alert from your vulnerability management system (e.g., Dependency-Track).
  2. Dependency-Track, which has ingested SBOMs for all your deployed artifacts, immediately tells you exactly which applications, versions, and deployments contain the vulnerable component.
  3. You can prioritize patching efforts based on the criticality of the affected applications and the severity of the vulnerability.
  4. Your CI/CD pipeline automatically generates updated SBOMs for patched versions, allowing for quick verification that the vulnerability has been remediated.
  5. Response time is reduced from weeks to hours or even minutes, significantly mitigating your organization’s risk exposure.

Challenges with SBOMs

While powerful, SBOMs aren’t a silver bullet:

  • Granularity: Determining the right level of detail. Too little and it’s useless, too much and it’s unwieldy.
  • Accuracy: Ensuring the generated SBOM accurately reflects the deployed software, especially with complex build processes.
  • Maintenance: Keeping SBOMs up-to-date as software evolves.
  • Consumption and Analysis: Simply generating SBOMs isn’t enough; organizations need tools and processes to consume, analyze, and act on the information they provide.
  • Storage: Storing and associating SBOMs with their respective artifacts in a discoverable and immutable way.

Solution Part 2: Sigstore – A Foundation for Software Trust

While SBOMs provide transparency into *what* is in your software, they don’t inherently tell you *who* created it or *that it hasn’t been tampered with*. This is where Sigstore comes in. Sigstore is an open-source project that aims to make cryptographically signing software artifacts easy, ubiquitous, and secure for everyone. It’s a non-profit, vendor-neutral service backed by the Linux Foundation.

What is Sigstore and Why Do We Need It?

Sigstore provides a public good for signing software, enabling developers to sign all kinds of software artifacts (container images, binaries, SBOMs, manifest files) and allowing consumers to verify those signatures. It addresses critical challenges that have historically plagued software signing:

  • Complex Key Management: Traditional PKI (Public Key Infrastructure) involves managing long-lived signing keys, which is error-prone and a security risk.
  • Accessibility: Setting up and maintaining signing infrastructure is often too complex for individual developers or smaller projects.
  • Transparency: There’s no public, auditable record of what was signed, by whom, and when.
  • Scalability: Existing solutions often don’t scale well for the vast number of open-source projects and artifacts.

Sigstore simplifies the signing process significantly by removing the need for developers to manage their own signing keys and by providing a transparent, verifiable log of all signing events. This means consumers can verify that a piece of software originated from a trusted source and has not been altered since it was signed.

Core Components of Sigstore: Architecture (in words)

Sigstore is comprised of three main components that work in harmony:

1. Fulcio (Root CA):

  • Role: Fulcio acts as a certificate authority (CA) that issues short-lived, ephemeral X.509 signing certificates.
  • How it works: Instead of requiring developers to manage long-lived keys, Fulcio authenticates users via OpenID Connect (OIDC) providers (like Google, GitHub, Microsoft). When a developer wants to sign an artifact, their client (Cosign) sends an OIDC identity token to Fulcio. Fulcio verifies the token’s authenticity and, if valid, issues a temporary signing certificate (typically valid for 10 minutes) that’s tied to the developer’s verified OIDC identity (e.g., their GitHub username and email). This certificate includes the public key used for signing.
  • Benefit: Eliminates the need for developers to manage static private keys. The private key is generated on the fly, used once, and then discarded. The identity of the signer is cryptographically bound to an established OIDC identity.

2. Rekor (Transparency Log):

  • Role: Rekor is an immutable, append-only transparency log that publicly records all signing operations performed using Sigstore.
  • How it works: After an artifact is signed using a certificate from Fulcio, the resulting signature, the signing certificate, and the artifact’s digest are uploaded to Rekor. Rekor then stores this information in a cryptographically verifiable data structure, typically a Merkle tree. Each entry in Rekor is timestamped and cryptographically linked to previous entries, making it impossible to alter or remove entries without detection.
  • Benefit: Provides a public, auditable record of all software signing events. This transparency allows anyone to verify that a signature exists and has not been tampered with. It helps detect if a supply chain has been compromised, even if the signer’s identity or artifact storage is later compromised. If an attacker tries to sign a malicious artifact, that signing event would also be publicly logged, aiding detection.

3. Cosign (CLI Tool):

  • Role: Cosign is the user-facing command-line interface (CLI) tool that developers and consumers use to interact with Fulcio and Rekor.
  • How it works: Cosign orchestrates the entire signing and verification workflow. For signing, it generates an ephemeral key pair, obtains a certificate from Fulcio using the developer’s OIDC identity, signs the artifact, uploads the signature and certificate to an OCI registry (or other storage), and records the signing event in Rekor. For verification, Cosign retrieves the signature and certificate, checks the certificate against Fulcio’s root of trust, and verifies the entry in Rekor.
  • Benefit: Simplifies the entire process for end-users, hiding the complexity of PKI, key management, and log interaction. It supports signing various artifact types, including OCI images, blobs, and even SBOMs.

The Workflow (Developer’s Perspective):

  1. A developer wants to sign a Docker image. They use the cosign sign command.
  2. Cosign generates an ephemeral key pair locally.
  3. Cosign connects to Fulcio, authenticating the developer via their OIDC provider (e.g., GitHub, triggering a browser-based login).
  4. Fulcio verifies the OIDC identity and issues a short-lived X.509 certificate containing the public key generated by Cosign.
  5. Cosign uses this certificate to sign the Docker image’s digest.
  6. Cosign then pushes the signature and the Fulcio-issued certificate as OCI artifacts to the same registry where the Docker image is stored.
  7. Finally, Cosign sends the signature, certificate, and artifact digest to Rekor, which logs the entire event and provides a transparency log entry ID.

The Workflow (Consumer’s Perspective):

  1. A consumer wants to verify a Docker image. They use the cosign verify command.
  2. Cosign retrieves the signature and certificate associated with the image from the OCI registry.
  3. Cos
Written by

Khader Vali

Senior Software Engineer specializing in cloud architecture, real-time systems, and enterprise-scale applications.

Share this article

Related Articles

Observability with Prometheus, Grafana & OpenTelemetry

Jul 03, 2026 · 15 min read

Prometheus, Grafana, OpenTelemetry: The Observability Trio

Aug 13, 2026 · 12 min read

GitHub Actions CI/CD: From Basics to Matrix Builds

Aug 23, 2026 · 17 min read