Supply Chain Security in CI/CD: NIST, SLSA, and What to Do First

Craig CookFounderLinkedInGitHub9 min read

Most of what runs in your pipeline is code you did not write and did not review. Third-party actions, base images, packages resolved at build time, the runner image itself. Supply chain security in CI/CD is the practice of constraining that borrowed code: knowing what it is, fixing which version of it runs, and being able to prove afterwards what went into a build.

Two reference points get cited constantly and are worth understanding properly rather than name-dropping: NIST SP 800-204D for strategy, and SLSA for build integrity. The broader set of controls a pipeline enforces is covered in the guide to CI/CD security; what follows is the supply-chain slice.

What the attack actually looks like

In March 2025 a widely used GitHub Action had its tags repointed at code that wrote CI secrets into build logs. Nobody edited a workflow file. Pipelines referencing that action by tag executed the new code on their next run, with whatever credentials the job happened to hold.

That shape is worth internalising because it is not a vulnerability in the usual sense. Nothing was exploited in your code. A dependency you had already decided to trust changed underneath you, and the pipeline did exactly what it was told. Every mitigation below is a variation on reducing how much can change without you noticing.

What NIST SP 800-204D is, and is not

NIST published SP 800-204D in February 2024 under the title Strategies for the Integration of Software Supply Chain Security in DevSecOps CI/CD Pipelines. It targets cloud-native applications built from loosely coupled services through CI/CD, and it maps its recommendations back to the practices in the Secure Software Development Framework, which is why the two tend to be read together.

It is guidance, not a certifiable standard. There is no such thing as being 800-204D certified, and it does not have a numbered control catalogue in the way ISO 27001 Annex A does. Treating it as a checklist misrepresents it. Its value is as a structured argument about where in a pipeline supply-chain risk concentrates, which makes it a useful citation when you need to justify the work to somebody who wants a reference.

SLSA, and why the level numbers changed

SLSA is a framework for build integrity, and the practical question it answers is whether you can trust that an artefact came from the source you think it did. Before quoting a level at anyone, check which version they mean, because the numbering was restructured and a great deal of published content still uses the old scheme.

Version 0.1 had a single unnamed track numbered 1 to 4. Version 1.0 introduced tracks, currently publishes only the Build track, and numbers it L0 to L3. SLSA 4 does not exist in the current Build track. If a vendor page or an internal policy references it, that document predates v1.0 and is worth re-reading before it becomes a requirement somebody has to meet.

The current levels are short enough to state plainly. Build L0 offers no guarantees. Build L1 means provenance exists describing how the artefact was built, though it may be unsigned. Build L2 adds a hosted build platform and digitally signed provenance. Build L3 adds hardening: runs cannot influence one another, and the signing material is unreachable from user-defined build steps.

What Build L2 takes in a real workflow

On GitHub Actions this is closer than most teams assume. Artifact attestations bind an artefact and its digest to a SLSA provenance predicate, signed with a short-lived certificate issued by Sigstore. Adding that step to a workflow provides SLSA v1.0 Build Level 2 on its own, and combining it with reusable workflows can reach Build Level 3.

There is a caveat that rarely appears in the write-ups, and it decides whether this is available to you at all. Artifact attestations work in public repositories on every plan. For private or internal repositories they require GitHub Enterprise Cloud. A team on a smaller plan with private repositories cannot reach Build L2 by this route regardless of how the workflow is written, which is worth establishing before anyone commits to a level in a roadmap.

One implementation note that saves a later migration: the provenance action has been folded into a more general attestation action, and new workflows should use the general one. Existing workflows on the older action keep working, so this is a preference rather than an urgent change.

An SBOM answers one question well

A software bill of materials lists what went into a build. Generating one in CI is a single step, and the value is specific: when the next widely-exploited library lands, an SBOM turns the question of whether you are affected from an afternoon of grepping into a query.

Be precise about what it does not do. An SBOM is an inventory, not a control. It does not stop a compromised dependency entering the build, it does not tell you whether a listed component is actually reachable in your code, and an SBOM generated once and filed away decays immediately. The value comes from generating it on every build and keeping it with the artefact, so the inventory and the thing it describes stay together.

Where supply chain security in CI/CD actually starts

Signed provenance is the most satisfying of these controls and the wrong place to begin. The cheapest meaningful step is pinning the third-party units your pipeline already executes, because it directly addresses the attack described at the top and it is a configuration change rather than a programme of work.

That control is also the one with the most provider-specific detail, including one provider where the standard advice cannot be followed as written. The mechanics per provider are covered in pinning CI dependencies across providers.

A workable order: pin what you already run, generate an SBOM on every build, then add signed provenance once the first two are habitual. Each step is useful alone, which matters because supply-chain programmes that sequence everything behind a target level tend to deliver nothing for two quarters.

Where CI/CD Watch fits

CI/CD Watch, a CI/CD observability platform that monitors pipelines across GitHub Actions, GitLab CI, Bitbucket Pipelines, CircleCI, Azure DevOps, and Jenkins, audits pipelines for whether artefact signing and SBOM generation steps are present, and whether third-party units are referenced by mutable refs. Findings are dated and structured per repository.

What it checks is presence, not sufficiency. A signing step that runs is evidence the practice exists; whether your provenance would satisfy an assessor at a given SLSA level is a question about how the build is isolated and how the key is held, and no static inspection of a workflow file answers it. Anyone claiming to award you a SLSA level from pipeline configuration alone is overstating what configuration shows.

The first useful hour

List the third-party units your pipelines execute and how each is referenced. That list is usually shorter than expected and almost always contains something nobody remembers adding. It also tells you, without any tooling, roughly how exposed you are to the failure mode at the top of this piece.

To get that list across a mixed estate rather than one repository at a time, connect a provider and run an audit. How each control is detected, including the per-provider handling, is in the security insights docs.

CI/CD Watch is built by 3CS Technologies Ltd, a UK consultancy that has run pipeline audits across regulated programmes and now runs the same engine inside the SaaS platform. We treat CI/CD security as a set of controls that either run on every commit or do not exist, which is why presence is what we check.

Related articles

Ready to monitor your CI/CD pipelines?

Connect your first provider in under two minutes. No credit card required.