Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Software Supply Chain Security

Overview

The software supply chain encompasses everything between writing source code and deploying running software: dependencies, build tools, CI/CD pipelines, artifact storage, and deployment mechanisms. Attacks on the supply chain—SolarWinds (2020), Codecov (2021), Log4Shell (2021), ua-parser-js (2021), xz-utils (2024)—have made supply chain security a top priority. This chapter covers the frameworks, tools, and practices for securing the software supply chain.

Artifact Provenance

Provenance is a verifiable record of how an artifact was produced: what source code, build environment, toolchain, and build steps were used. Provenance enables consumers to verify that an artifact was built from the claimed source by an authorized process.

SLSA (Supply-chain Levels for Software Artifacts)

SLSA is a security framework with four levels of increasing assurance:

LevelNameGuaranteeRequirements
1Documented buildProvenance existsProvenance metadata (who, what, how)
2Hosted buildTamper-proof buildHermetic build platform, authenticated provenance
3Hardened buildChange-protected buildNon-falsifiable provenance, build platform security
4Hermetic + reproducibleMaximum assuranceTwo-party review, reproducible builds, hermetic

SLSA Level 3 requires non-falsifiable provenance—the provenance must be generated by the build platform itself (not the developer) and signed by a key the developer cannot access. This prevents tampering with the provenance after the build.

In-Toto

in-toto provides a framework for verifying the integrity of the software supply chain as a whole (not just individual artifacts):

  • Layout: defines the expected supply chain steps (fetch, build, test, package) and authorized functionaries
  • Attestations: each step produces a signed metadata file describing what it did
  • Verification: consumers verify the full chain—every step was performed by an authorized party, in the correct order, with the expected inputs
Source → fetch (attestation) → build (attestation) → test (attestation) → package (attestation)
                                                                         │
                                                                    Verify chain:
                                                                    - All steps signed
                                                                    - Correct order
                                                                    - Expected functionaries

SBOM (Software Bill of Materials)

An SBOM is a comprehensive list of all components in a software package—libraries, frameworks, dependencies, versions, licenses, and relationships. It is essential for vulnerability management and incident response.

SBOM Standards

StandardFormatAdoption
SPDXJSON/XML, ISO/IEC 5962:2021Linux Foundation, widely adopted
CycloneDXJSON/XML, OWASP projectGrowing adoption, lightweight
SWIDXML, ISO/IEC 19770-2Enterprise, Microsoft ecosystem

An SBOM should include: component name, version, supplier, unique identifier (CPE, PURL), relationships (depends-on, contains, patches), license information, and vulnerability references (CVE IDs).

U.S. Executive Order 14028 (May 2021) mandates SBOMs for all software sold to the federal government, dramatically accelerating adoption.

SBOM in Practice

  • Generation: Syft (Anchore), Trivy, Microsoft SBOM Tool, SPDX tool
  • Consumption: Grype (vulnerability matching), dependency-track (OWASP), GUAC (Google’s supply-chain graph)
  • Storage: VEX (Vulnerability Exploitability eXchange) — SBOM + vulnerability status

Sigstore & Cosign

Sigstore provides a free, open-source code-signing infrastructure:

  • Cosign: sign and verify container images and artifacts using keyless signatures (OIDC-based, no key management)
  • Fulcio: certificate authority that issues short-lived certificates based on OIDC identity (e.g., GitHub Actions identity)
  • Rekor: transparency log for signatures—every signature is publicly recorded, enabling detection of rogue certificates
Sign:
  Developer → OIDC auth (GitHub) → Fulcio (issues certificate) → Cosign (signs image) → Rekor (logs signature)

Verify:
  Verifier → Rekor (check transparency log) → Fulcio (verify certificate chain) → Cosign (verify signature)

Key innovation: keyless signing eliminates the key distribution problem. Identity is bound to the signing event through OIDC (GitHub Actions, Google identity, etc.), not through pre-shared keys.

Binary Transparency & Package Signing

Binary Transparency

Modeled on Certificate Transparency (CT), binary transparency ensures that compiled binaries are publicly logged, enabling detection of unauthorized builds:

  • Grafeas: Google’s artifact metadata API for storing and querying attestation metadata
  • Binary Transparency (note): academic proposal; production systems use Sigstore’s Rekor as a general-purpose transparency log

Package Signing

  • npm: package provenance via Sigstore (built into npm publish)
  • Python: Trusted Publishing (OIDC-based, Sigstore-backed) on PyPI
  • RubyGems: Sigstore-based signing for gems
  • OCI registries: Cosign for container image signing

Attack Vectors

Dependency Confusion

Dependency confusion exploits package managers that prefer private (internal) packages over public ones. An attacker publishes a malicious package on a public registry with the same name as an internal package; when a build resolves dependencies, it may accidentally fetch the public (malicious) version instead of the private one.

Mitigation: namespace reservation, scoped packages (e.g., @company/package), registry configuration that prefers internal sources, and build tool flags that enforce internal-only resolution for internal packages.

Typosquatting

Attackers publish packages with names similar to popular libraries (e.g., reqeusts instead of requests). Automated tooling and IDE autocomplete can inadvertently install these.

Mitigation: lockfiles with integrity hashes, allow-lists of approved packages, namespace scoping, and monitoring (Socket.dev, PyPI advisor).

Malicious Dependencies

Supply chain attacks where a maintainer account is compromised or a legitimate maintainer introduces malicious code:

  • Account takeover: steal credentials of library maintainers (e.g., event-stream, ua-parser-js, xz-utils)
  • Maintainer malice: maintainer intentionally introduces backdoors
  • Transitive dependency attacks: compromise a widely-depended-upon library

Compiler Supply Chain

The ultimate supply chain attack: compromise the compiler itself. Reflections on Trusting Trust (Thompson, 1984) demonstrated that a compromised compiler can inject backdoors into compiled programs, and the backdoor survives even if you recompile the compiler from clean source.

Mitigation: bootstrappable builds (e.g., Guix’s bootstrappable packages), diversifying compilers (different compilers for different builds), and reproducible builds (compare output from independent build environments).

Dependency Risk Scoring & SCA

Software Composition Analysis (SCA) tools scan dependencies for known vulnerabilities:

ToolScanning ApproachIntegration
SnykVulnerability DB + license complianceCI/CD, IDE, CLI
DependabotGitHub-native, auto-PR for updatesGitHub
TrivyContainer + filesystem + git scanningCI/CD, Kubernetes admission
GrypeSBOM-based vulnerability matchingCI/CD
Socket.devBehavioral analysis (not just CVEs)npm, PyPI

Risk scoring combines multiple signals: known vulnerabilities (CVEs), maintainer activity, dependency staleness, license compatibility, and behavioral indicators (does the package access network, file system, or environment variables unexpectedly?).

Vulnerability Reachability

Not all vulnerabilities in an SBOM are exploitable. Reachability analysis determines whether a vulnerable function is actually called by your application:

  • If a library has a CVE in function X, but your code never calls X, the vulnerability is not reachable
  • Reachability reduces false positives by 80–95% compared to naive CVE matching
  • Tools: Snyk Code, GitHub Advisory Database (with reachability), Semgrep Supply Chain

Secure CI/CD

Ephemeral Runners

CI runners should be ephemeral: created fresh for each build, destroyed after completion. This prevents:

  • Cross-contamination: secrets or artifacts from one build leaking into another
  • Persistent compromise: an attacker who compromises a runner gains nothing persistent
  • State accumulation: no stale caches, no leftover build artifacts

Isolated & Sandboxed Builds

Build steps should run in sandboxed environments:

  • Container isolation: each step in its own container
  • Network restrictions: builds can only access declared network endpoints
  • Secret injection: secrets injected at runtime via OIDC, not baked into images
  • No self-hosted runners for open source: use ephemeral cloud runners to prevent persistent supply chain compromise (GitHub’s Open Source CI hardening)

Secure Pipeline Patterns

┌──────────────────────────────────────────────────────┐
│                  Secure CI/CD Pipeline                │
│                                                      │
│  Source → Lint → Build → Test → Sign → Scan → Deploy │
│    │                              │         │        │
│  provenance                  Cosign    SBOM +    Attest │
│  attestation                 (Sigstore) vulnerability   │
│                                        check           │
│                                                      │
│  Principles:                                         │
│  - Least privilege (narrow permissions per step)      │
│  - Ephemeral runners (no persistent state)           │
│  - OIDC-based identity (no long-lived secrets)       │
│  - Hermetic builds (no host access)                   │
│  - Signed + attested artifacts                        │
└──────────────────────────────────────────────────────┘

Artifact Registries & OCI Artifacts

OCI (Open Container Initiative) Artifacts

The OCI image spec was extended to support arbitrary artifacts beyond container images:

  • Helm charts: stored as OCI artifacts in registries
  • SBOMs: attached as referrers to images
  • Attestations: Sigstore attestations linked to images via digests
  • WASM modules: OCI-stored WebAssembly components

This convergence means a single registry (Docker Hub, ECR, GCR, GAR, GHCR) can store all artifact types with a unified signing and verification workflow.

WASM Package Ecosystems

WebAssembly packages are emerging as a language-agnostic distribution format:

  • wasm-pkg: OCI-native WASM component registry
  • Warg: bytecode alliance’s package registry for WASM components
  • Registries: store compiled WASM components with metadata, versioning, and OCI-compatible signing

WASM components are language-independent (can be produced from Rust, C++, Go, AssemblyScript, etc.) and run in any WASM runtime (Wasmtime, WasmEdge, wasmer, browsers).

Interview Angle

“How would you secure a CI/CD pipeline against supply chain attacks?”

Layer defenses: (1) ephemeral runners with no persistent state, (2) OIDC-based identity (no secrets stored in CI), (3) hermetic builds in sandboxed containers, (4) signed artifacts with Sigstore/Cosign, (5) SBOM generation at build time, (6) vulnerability scanning with reachability analysis before deployment, (7) provenance attestation linking artifact back to source commit, (8) allow-lists for dependencies (no new packages without review), (9) branch protection requiring review before builds are promoted to production artifacts.

“Explain dependency confusion and how to prevent it.”

Dependency confusion exploits the priority order of package managers. If an internal package @myco/auth-lib exists only in your private registry, and an attacker publishes auth-lib or @myco/auth-lib on the public registry, a build that checks the public registry first will install the malicious version. Prevention: (1) scoped packages with unique org prefixes, (2) configure package managers to check private registries first, (3) use registry allow-lists that reject unapproved packages, (4) monitor public registries for your package names (automated alerts).

Key References

  • SLSA specification (slsa.dev)
  • Sigstore documentation (sigstore.dev)
  • in-toto attestation framework (in-toto.io)
  • SPDX specification (spdx.dev)
  • Thompson, “Reflections on Trusting Trust” (1984)
  • U.S. Executive Order 14028 on Improving the Nation’s Cybersecurity (2021)