Back to Articles
📄
software supply chainSBOMartifact signingSigstoreCosignSLSAcontainer security

Software Supply Chain Security: SBOMs, Artifact Signing, and the New Baseline

When attackers hijack build pipelines, the damage spreads to thousands of systems. Knowing exactly what’s inside each artifact and being able to prove it hasn’t been tampered with: through SBOMs and modern signing tools: turns the supply chain from a blind spot into a defensible frontier.

Software Supply Chain Security: SBOMs, Artifact Signing, and the New Baseline

In 2020, attackers compromised SolarWinds' build pipeline and distributed a backdoored update to roughly 18,000 customers, including US government agencies.
In 2021, a malicious package was injected into the Codecov bash uploader, exposing secrets from thousands of CI pipelines.
In 2021, a critical vulnerability in Log4j, a logging library embedded in hundreds of thousands of applications, took months to fully remediate because organizations did not know where they were using it. Because they lacked an inventory of Log4j’s presence, they could not locate all affected systems quickly.
These incidents share a common thread: the attack surface was not the application code, but the pipeline that built and delivered it.
Software supply chain security is the discipline of verifying the entire chain from source code to running artifact, not just the code itself.

What the Software Supply Chain Is

Every piece of software has a supply chain: the source code, the dependencies it imports, the tools that compile it, the pipeline that builds it, the registry that stores the artifact, and the infrastructure that runs it.
An attacker who can compromise any link in that chain can compromise the final product.

Source code
    ↓
Dependencies (npm, Maven, PyPI, Go modules)
    ↓
Build tools (compiler, bundler, test runner)
    ↓
CI/CD pipeline (GitHub Actions, Jenkins, GitLab CI)
    ↓
Artifact registry (Docker Hub, ECR, Artifactory)
    ↓
Deployment infrastructure (Kubernetes, ECS, Lambda)
    ↓
Running application

Traditional security focused on the application code; supply‑chain security, by contrast, watches every arrow in that diagram. Because attackers can insert malicious code before the application ever runs, focusing only on runtime checks leaves a blind spot.

SBOMs: Knowing What You Ship

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 and licenses.
It is the software equivalent of an ingredients list.

The US Cybersecurity and Infrastructure Security Agency (CISA) published minimum SBOM elements in 2021 and updated guidance in 2023.
That guidance establishes these as a baseline expectation for software sold to or used by US federal agencies, and increasingly, for any organization that takes supply chain security seriously.

SBOM formats

Two formats dominate:

SPDX (Software Package Data Exchange): an ISO standard (ISO/IEC 5962:2021) originally developed by the Linux Foundation. Widely supported by open‑source tooling.

CycloneDX: developed by OWASP, designed specifically for security use cases. Supports vulnerability data, license compliance, and dependency graphs.

// CycloneDX SBOM fragment
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "components": [
    {
      "type": "library",
      "name": "express",
      "version": "4.18.2",
      "purl": "pkg:npm/express@4.18.2",
      "licenses": [{ "license": { "id": "MIT" } }],
      "hashes": [{ "alg": "SHA-256", "content": "abc123..." }]
    }
  ]
}

Generating SBOMs

SBOMs can be generated at build time from package manifests, or by scanning container images. Common tools:

# Generate SBOM from a container image (Syft)
syft nginx:latest -o cyclonedx-json > nginx-sbom.json

# Generate SBOM from a Node.js project
syft dir:. -o spdx-json > app-sbom.json

# Scan SBOM for known vulnerabilities (Grype)
grype sbom:./app-sbom.json

A Software Bill of Materials (SBOM) provides defensive utility only when cryptographically signed and continuously reconciled with artifact deployments. A static, unverified SBOM that diverges from running container layers generates false security confidence while allowing zero-day vulnerabilities in transitively loaded binaries to persist undetected.

Artifact Signing: Verifying What You Deploy

Knowing what is in an artifact is not enough if you cannot verify that the artifact has not been tampered with between build and deployment.
Artifact signing provides that guarantee. Without a signature, an attacker could replace the binary with a trojan and the deployment would proceed unnoticed.

Sigstore and Cosign

Sigstore is an open‑source project (backed by the Linux Foundation, Google, Red Hat, and Purdue University) that provides a free, transparent signing infrastructure.
Cosign is its tool for signing and verifying container images and other artifacts.

# Sign a container image (keyless, using OIDC identity)
cosign sign ghcr.io/myorg/myapp:v1.2.3

# Verify before deployment
cosign verify ghcr.io/myorg/myapp:v1.2.3 \
  --certificate-identity=https://github.com/myorg/myapp/.github/workflows/release.yml@refs/heads/main \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com

Keyless signing uses the CI system's OIDC identity (e.g., a GitHub Actions workflow) rather than a long‑lived key.
The signing event is recorded in Rekor, Sigstore's transparency log, a tamper‑evident, append‑only record of every signing event. This means you can verify not just that an image was signed, but when and by which workflow.

SLSA: Supply‑chain Levels for Software Artifacts

SLSA (pronounced “salsa”) is a framework developed by Google and now maintained by the OpenSSF that defines four levels of supply chain integrity:

Level What it guarantees
SLSA 1 Build process is documented; SBOM is generated
SLSA 2 Build is hosted on a version‑controlled platform; provenance is generated
SLSA 3 Build is isolated; provenance is non‑falsifiable
SLSA 4 Two‑person review; hermetic, reproducible builds

SLSA provenance is a signed attestation that describes how an artifact was built: which source commit, which build system, which inputs.
It allows a consumer to verify not just that an artifact is signed, but that it was built from a specific commit using a specific pipeline.

# Generate SLSA provenance in GitHub Actions
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1
  with:
    image: ghcr.io/myorg/myapp
    digest: ${{ steps.build.outputs.digest }}

Dependency Integrity

Dependencies are the largest attack surface in most software supply chains.
Dependency confusion attacks (where a malicious package with the same name as an internal package is published to a public registry) and typosquatting attacks (where a package with a name similar to a popular one is published with malicious code) are both well‑documented.

Mitigations:

Lock files with integrity hashes. package-lock.json, yarn.lock, Pipfile.lock, and go.sum all record the exact version and hash of every dependency. Verify that lock files are committed and that CI installs from the lock file, not from a floating version range.

Private registries with allow‑lists. Route all dependency fetches through a private registry (Artifactory, Nexus, AWS CodeArtifact) that only proxies approved packages. This prevents dependency confusion attacks.

Automated vulnerability scanning. Tools such as Dependabot, Renovate, Snyk, and OWASP Dependency‑Check scan dependencies against known vulnerability databases (NVD, OSV) and open pull requests for updates.

# GitHub Dependabot configuration
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10

Why Signing Alone Is Not Enough

Artifact signing proves that an image was signed by a specific identity at a specific time.
It does not prove that the image is free of vulnerabilities, that the build process was not compromised before signing, or that the source code was reviewed.
Signing is one control in a layered defense, it closes the tampering‑in‑transit gap, but it does not close the compromised‑build or vulnerable‑dependency gaps. Therefore, a robust strategy layers signing with provenance, dependency checks, and pipeline hardening.

This is why SLSA levels matter: they extend the trust chain backwards from the signed artifact to the build process itself.
A SLSA 3 attestation says not just “this image was signed” but “this image was built from this specific commit by this specific isolated pipeline, and that claim is non‑falsifiable.”
The combination of signing (Cosign) and provenance (SLSA) closes significantly more of the supply chain attack surface than either alone.

Putting It Together: A Minimal Supply Chain Security Baseline

For most teams, a practical baseline looks like this:

  1. Generate an SBOM at build time and attach it to every release artifact.
  2. Sign artifacts using Cosign with keyless signing in CI.
  3. Verify signatures before deployment, in the CD pipeline and in admission controllers (e.g., Kyverno or OPA Gatekeeper in Kubernetes).
  4. Lock dependencies and scan them for vulnerabilities on every PR.
  5. Use a private registry to prevent dependency confusion.
  6. Audit the CI pipeline itself: restrict who can modify workflow files, use pinned action versions (by commit hash, not tag), and rotate secrets regularly.

Following these steps gives you visibility into what you ship, assurance that it hasn’t been altered, and confidence that the build environment behaved as expected.

# Kubernetes admission policy: require signed images (Kyverno)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-signed-images
spec:
  rules:
    - name: verify-image-signature
      match:
        resources:
          kinds: ["Pod"]
      verifyImages:
        - imageReferences: ["ghcr.io/myorg/*"]
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/myorg/*"
                    issuer: "https://token.actions.githubusercontent.com"

Sources & References

  1. [1]
  2. [2]
  3. [3]
  4. [4]
  5. [5]
  6. [6]
  7. [7]
  8. [8]
  9. [9]
  10. [10]
  11. [11]

Comments (0)

Loading comments...