123% more reported CVEs per day in 2026 than last year.

Supply chain

Software supply chain security best practices

A practical checklist, from the first commit to what you do after release. Each section starts with the steps that give the most protection for the least work, so you can stop at any point and still be better off.

Updated

Source

  • Require strong authentication. Use multi-factor authentication for every code hosting account.
  • Protect the main branch. Require review before merge, and do not let anyone push straight to a release branch.
  • Keep secrets out of code. Scan for them on every push, and rotate anything that has been exposed.
  • Treat workflow files as code. A change to a pipeline can reach your secrets, so require owners to review them.

Dependencies

  • Commit a lockfile and install from it. Use npm ci and its equivalents, so that builds do not pick up new versions by accident. A lockfile has limits, but it is the place to start.
  • Add a waiting period for new versions. Malicious releases are often caught soon after they appear, so not adopting a version on the day it is published gives that a chance to happen.
  • Limit install scripts. Disable them where you can. Scripts that run on install are how npm worms spread.
  • Vet new dependencies. Check the name for typosquatting, and look at maintenance and popularity. OpenSSF Scorecard automates part of this.
  • Protect internal package names. Use scopes and registry configuration, so that a public package cannot take the place of an internal one through dependency confusion.
  • Trim what you do not need. Every dependency is something else to monitor.

Build and CI/CD

  • Pin GitHub Actions to a full commit hash. Tags can be moved, as the tj-actions compromise showed.
  • Limit what each job can do. Give the workflow token the least permission it needs, and use short-lived credentials instead of long-lived secrets.
  • Restrict outbound traffic. A build needs packages from known sources and publishes to known places. Block everything else, and stolen secrets have nowhere to go. See GitHub Actions egress policy.
  • Run each job in a fresh, isolated environment. Nothing should carry over from one job to the next, least of all from a pull request by an outside contributor.
  • Treat caches as an input. A poisoned cache survives between builds, and what it restores is easy to overlook. See GitHub Actions cache.

For the full list, see the CI/CD pipeline security checklist and how runner security compares.

Release

  • Generate an SBOM for every release, from the build. Keep it with the artifact. See SBOM best practices.
  • Sign artifacts and publish provenance. Consumers can then check where a release came from. SLSA sets out the levels.
  • Build releases only in CI. A release from a laptop has no reliable record behind it.
  • Use one artifact from test to production. Promote what you tested, rather than rebuilding it, so that the record stays true.

After release

  • Monitor what you shipped. Keep checking the SBOMs of supported releases against new vulnerabilities.
  • Prioritize with more than CVSS. Use CISA KEV, EPSS and context. See how to prioritize vulnerabilities.
  • Know how long you were exposed. Build history shows which releases contained a package, and from when.
  • Have a plan before you need it. Decide who triages, who fixes and who talks to customers. See the vulnerability management lifecycle.
  • Practice with a real scenario. Ask how long it would take to find every release with a given package. If the answer is days, start there.

What to do first

When Do this
This week Multi-factor authentication, lockfiles in CI, pinned GitHub Actions, least-privilege workflow tokens
This month SBOM from every release build, dependency alerts with an owner, secret scanning
This quarter Outbound traffic rules for builds, monitoring of shipped releases, a tested response plan
Next Signed provenance, a formal review of SLSA or NIST SSDF coverage, supplier SBOMs

Which of these CRACI handles

CRACI covers the build and everything after it. As your GitHub Actions runner, it runs each job in its own isolated virtual machine, records every package the job fetches into an SBOM, marks packages restored from CI caches, and enforces an egress policy that blocks connections your build does not need. It then keeps checking what shipped, shows which builds contained a vulnerable package, and can block builds with policy gates.

The rest stays with your other tools: CRACI does not scan source code or secrets, does not detect new malicious packages by behavior, and does not sign SBOMs or provenance. See software supply chain security tools compared for what fills each gap.

Software supply chain security best practices: frequently asked questions

How do you secure a software supply chain?

Know what you ship with an SBOM from every release build, control what gets in with lockfiles and vetting, protect the build by limiting secrets and outbound traffic, and keep monitoring what you released.

What should a small team do first?

Turn on multi-factor authentication, install from lockfiles in CI, pin GitHub Actions to commit hashes and give workflow tokens the least permission they need. Those steps take days and close common attack paths.

How do you prevent malicious packages?

No single step does. Delay adopting new versions, limit install scripts and vet new dependencies. Restricting outbound traffic from builds limits the damage if a malicious package gets through.

Why pin GitHub Actions to a commit hash?

Because a version tag can be moved to different code. A full commit hash always refers to the same code, so a hijacked tag does not reach your pipeline.

How often should you review your supply chain?

Monitoring should be continuous. Review your dependency policy, workflow permissions and response plan at least yearly, and after any incident in your stack.

Cover the build and what follows

Move a GitHub Actions workflow to CRACI and get SBOMs, egress control and monitoring of what you ship.

Book a demo