Secure Code/Guide

Software supply chain security: lockfiles, SBOMs and signed builds

Much of the code you ship was written by someone else. How to pin and review dependencies, avoid typosquatting and dependency confusion, produce an SBOM and check what you install.

High impact6 min readDevelopers, AdminsUpdated 31 October 2026

Fingerprint of this page: sha256("/secure-code/software-supply-chain/")

A typical web application often contains more third-party code than code written by its own team. Every library, build plugin, container base image and CI step is part of your software supply chain, and each one is a way for a mistake or an attacker to reach your users. In the OWASP Top 10:2025, Software Supply Chain Failures ranks third, as a broader successor to the 2021 category for vulnerable and outdated components. The most effective defences are ordinary engineering habits, applied consistently.

Lockfiles and reproducible installs

A version range such as ^4.18.0 in package.json lets the package manager pick a newer release on each install. A records the exact version and an integrity hash of every package, including the indirect dependencies you never chose yourself. Commit the lockfile, and make every build install exactly what it says.

bashCI build step
# Node.js: install exactly what package-lock.json specifies
npm ci

# PHP: install from composer.lock, never run "composer update" in CI
composer install

# Python: install pinned versions and reject anything without a matching hash
pip install --require-hashes -r requirements.txt

npm ci needs an existing lockfile, stops with an error if it disagrees with package.json, removes any existing node_modules and never writes to either file. That is what you want in a pipeline: the same input produces the same install, and a drifted lockfile fails loudly instead of being silently updated.

Review updates instead of avoiding them

Pinning without updating swaps one risk for another, because you stay on versions with known vulnerabilities. Use an automated dependency update tool that opens one pull request per update, let your tests run on it and read the changelog for major versions. Group small patch updates so the queue does not turn into noise that people approve without reading.

Install scripts deserve attention. Package managers can run code from a dependency during installation, and many malicious packages act exactly at that moment. Where your project works without them, disable install scripts in CI (with npm, the --ignore-scripts option) and find out which packages genuinely need a build step.

Typosquatting, dependency confusion and hijacked packages

  • : a malicious package with a name close to a popular one, waiting for a typing error or a careless copy from a forum post. Check the exact name and the publisher before you install.
  • : your build uses an internal package name that does not exist on the public registry. Someone publishes that name publicly with a higher version number, and a misconfigured resolver prefers it. Use a scope or namespace you own, and configure the package manager to fetch internal names only from your private registry.
  • Account takeover: a real maintainer’s account or publishing token is stolen, and a poisoned release appears under a trusted name. Your lockfile protects you until you update, which is why updates deserve a short review.
  • A malicious maintainer: rarely, the person in control of a package becomes the attacker, as the xz case below shows.

Malicious packages in public registries are reported regularly, and most follow these patterns. Typical payloads read environment variables and tokens at install time and send them elsewhere, which is one more reason to keep long-lived secrets out of build environments.

SBOMs, signatures and provenance

A software bill of materials () is a machine-readable inventory of the components in a build, with versions and identifiers. When a new vulnerability is announced, an SBOM answers “are we affected?” in minutes instead of days. Two open formats dominate:

  • CycloneDX, developed by OWASP and standardised by Ecma International as ECMA-424, with JSON, XML and Protocol Buffers encodings. It also covers related documents such as VEX statements, which say whether a known vulnerability actually affects a product.
  • SPDX, a Linux Foundation project published as the international standard ISO/IEC 5962:2021, with deep roots in licence information. Version 3.0 added profiles for security and build data.

Generate the SBOM in the build pipeline, not by hand, store it with each release and feed it to a vulnerability scanner. Many build tools and scanners can write both formats.

A signature proves who published an artefact. Sigstore, an open-source project backed by the OpenSSF, makes signing practical without long-lived keys: the signer proves their identity through an OpenID Connect login, receives a short-lived certificate, and the signature is recorded in a public . goes further and records how an artefact was built: from which source, on which build platform, with which inputs.

SLSA (Supply-chain Levels for Software Artifacts) arranges these guarantees in levels. The current specification, version 1.2, has a Build track that runs from level 1, where provenance exists, through level 2, where a hosted build platform signs it, to level 3, where a hardened platform protects the build itself against tampering. It also adds a Source track. You do not need level 3 to benefit: signed provenance from a hosted CI system already closes several gaps.

Checksums and base images

When you download a tool or binary by hand, compare its SHA-256 checksum with the value the project publishes, ideally obtained over a different channel than the download itself, and verify the signature where one is offered. A checksum from the same compromised server proves little.

bashVerifying a download
# Print the SHA-256 of the file and compare it with the published value
sha256sum tool-1.2.3.tar.gz          # Linux
shasum -a 256 tool-1.2.3.tar.gz      # macOS

# Or let GNU coreutils compare against the project's checksum file
sha256sum --check --ignore-missing SHA256SUMS

Container images belong to the chain too. A minimal base image, such as a slim distribution or a distroless image without shell or package manager, contains fewer packages to patch and fewer tools for an intruder. Pin base images by digest rather than by a tag that can move, and rebuild on a schedule so security updates actually arrive.

The xz utils backdoor: a lesson in trust

In March 2024 a developer investigating unusually slow SSH logins and errors from a memory debugging tool on a Debian unstable system found a backdoor in xz utils, a compression library installed on most Linux distributions. Versions 5.6.0 and 5.6.1 contained the hidden code, tracked as CVE-2024-3094. OpenSSH does not use the library directly, but distributions that patch it for systemd notifications link it indirectly through libsystemd, which gave the code a path into the SSH server.

Three details make it a lesson rather than just a bug. The code came from a contributor who had built trust over roughly two years and gained maintainer rights. The code that activated the backdoor was not in the git repository, only in the release tarballs as a modified build script, while the payload itself sat in binary test files committed to the repository. And it was caught by one attentive engineer, before the affected versions had reached most stable distribution releases.

  • Build from the source repository, or compare release tarballs with the tagged source, so that code outside version control stands out.
  • Treat a small, overloaded maintainer team as a risk factor for critical dependencies, and support the projects you depend on.
  • Take performance anomalies and odd test failures seriously; they were the first signal here.
  • Keep the ability to roll back quickly. The official advice at the time was to return to an uncompromised version such as 5.4.6.

Sources and further reading

  1. npm Docs: npm cidocs.npmjs.com
  2. SLSA specification v1.2slsa.dev
  3. CycloneDX specification overviewcyclonedx.org
  4. SPDX overviewspdx.dev
  5. oss-security: backdoor in upstream xz/liblzma leading to ssh server compromiseopenwall.com
  6. CISA: Reported supply chain compromise affecting XZ Utils (CVE-2024-3094)cisa.gov

General information, checked on 31 October 2026. Test changes on one system first and keep a way back. Found something outdated? Tell the editors.

FAQ

Questions readers ask

Do I need an SBOM if nobody asks for one?

It is still useful internally. When a widely used library announces a critical vulnerability, an SBOM per release tells you quickly which products and versions are affected. Some customers and regulations already expect SBOMs, so producing them in the pipeline now avoids a rushed project later.

CycloneDX or SPDX?

Both are open standards and both work for vulnerability management. CycloneDX grew out of the security community and SPDX out of licence compliance, and both have since widened their scope. Pick the one your tools and customers support best; many generators can write both.

Is pinning exact versions enough?

Pinning makes installs repeatable, not safe. A pinned version with a known vulnerability stays vulnerable, so you still need a routine for updates. Pinning combined with reviewed, automated updates is what works.

What is the difference between a checksum and a signature?

A checksum shows that a file matches a published value, which detects corruption or a swapped download, but only if the published value is trustworthy. A signature also shows who produced the file, because only the holder of the signing key or identity could have created it.

Keep reading

More from Secure Code