Why Scanning Every Commit Is Not Enough: A Practical Guide to Software Supply Chain Security

Imagine a team that runs automated vulnerability scans on every pull request, enforces code review for every merge, and ships containers with confidence. Then one morning, their staging environment starts behaving strangely—not because of anything their developers wrote, but because a base image they pulled two weeks ago silently contained a compromised library. The scan passed. The code review passed. The trust assumption that broke everything was made before a single line of their own code was written.

Diagram of software supply chain security controls across build, registry, and runtime

This is the core problem with software supply chain security: the attack surface does not start at your source code. It starts wherever your software first touches something you did not write yourself.

The Chain Is Longer Than It Looks

A software supply chain covers the entire path from source code and third-party dependencies through the build system, the container registry, and on to the deployed runtime. Each link in that chain is a potential entry point for something unintended.

The threat is not hypothetical or distant. According to Sonatype’s 2025 data, more than 454,600 new malicious open-source packages were identified that year alone, bringing the cumulative known-and-blocked total across major ecosystems above 1.2 million. Over 99% of that 2025 malware was concentrated in npm. And crucially, some of the most alarming incidents were not the work of individual bad actors manually uploading rogue packages—they were automated campaigns. A self-replicating worm spread across hundreds of npm packages within days, and a single flooding campaign called IndonesianFoods injected over 169,000 packages into a registry within a matter of days. These are not slow, deliberate infiltrations. They move faster than any manual review process can react.

The implication for teams is that automated attacks can outpace reactive defenses. The question is not whether to act, but where in the delivery pipeline to place controls that slow or stop that propagation.

Where Trust Can Break Down

Before mapping controls, it helps to see the delivery flow as a sequence of trust decisions—each one a potential failure point.

flowchart TD
 A[Package registry / base image] --> B[Developer install or Dockerfile pull]
 B --> C[Build system / CI pipeline]
 C --> D[Container registry]
 D --> E[Deployment admission check]
 E --> F[Running container in production]
 F --> G[Runtime monitoring]

At every arrow in this diagram, something is implicitly trusted. A mutable tag like python:3.12 trusts that the image it resolves to today is the same one it resolved to last week. A CI job that pulls its own plugins from a public registry trusts those plugins. A deployment that skips policy checks trusts that everything before it was clean. When attackers understand this chain, they target the convenient points: mutable tags, overpermissioned CI tokens, unscanned base images, and unverified build environments. Scanning committed source code addresses almost none of these entry points.

Controls That Match the Risk

Rather than a single tool or audit step, effective supply chain security is a set of layered controls—each one addressing a different failure mode. The table below maps the key practices to the stages where they actually apply.

Delivery Stage Main Risk Control
Source and dependencies Malicious or drifting packages Dependency pinning by digest or hash, lock files verified in CI
Base image selection Inherited vulnerabilities, unknown contents Minimal verified images with SBOMs and provenance attestations
Build system / CI Injected malicious code, tampered artifacts Ephemeral build environments, pinned CI plugins, signed provenance
Container registry Unauthorized images, unvetted publishers Registry access controls, signature verification, image admission policies
Deployment Policy bypass, misconfigured workloads Admission controllers enforcing provenance and policy checks
Runtime Compromises that evade pre-deployment scanning Behavioral anomaly detection, deviation from baseline profiles

None of these stages can substitute for the others. A team that hardens its build system but pulls unverified base images has plugged one hole while leaving another open.

What SBOMs and Provenance Actually Tell You—and What They Don’t

Two terms come up repeatedly in supply chain security discussions, often used interchangeably: SBOMs and provenance. They answer different questions, and understanding the difference matters.

An SBOM (software bill of materials) is essentially an inventory. It tells you what components are inside an artifact—which libraries, which versions, which licenses. When a new vulnerability is disclosed, a team with current SBOMs can determine within minutes which running workloads contain the affected component. Without them, the same exercise can take days. Pairing SBOMs with VEX (Vulnerability Exploitability eXchange) data adds another layer: VEX documents indicate whether a known vulnerability in a component is actually exploitable in the specific context of your image, which helps reduce alert fatigue.

Provenance answers a different question entirely: where did this artifact come from, and how was it built? The SLSA framework defines provenance as the verifiable information describing where, when, and how a software artifact was produced. In practice, a provenance attestation records things like the source repository, the specific commit, the build configuration, and—critically—the identity of the build platform that ran the job.

This last point deserves emphasis. A provenance document that carries a signature is only as useful as the trust you place in the signer-builder pair. The SLSA specification is explicit: consumers must accept only specific signer-builder pairs—for example, GitHub can sign provenance for GitHub Actions, but not for Google Cloud Build. A signature from an unexpected or untrusted party should be treated as a red flag, not reassurance. Provenance alone, without verifying the builder identity and confirming that the signer and builder are a trusted pair, is not enough.

Together, SBOMs and provenance form the transparency layer that makes the rest of the pipeline auditable. When an incident occurs—a compromised dependency, a malicious base image update—provenance and SBOMs are what allow a team to answer quickly: which artifacts were affected, which environments ran them, and when?

The Specific Weaknesses Attackers Exploit

Understanding the pattern of real attacks helps prioritize which controls to implement first. Several vulnerability patterns appear repeatedly in supply chain incidents:

Mutable tags. A Docker tag like :latest or :3.12 is a pointer, not a fixed reference. It can be updated by the upstream maintainer—intentionally or after a compromise—and your builds will silently pull the changed content. Pinning by SHA256 digest instead of tag eliminates this entire class of drift. The build either gets exactly the artifact it expects, or it fails with a clear error.

CI/CD as a high-value target. If an attacker can modify what your build system produces, they bypass source code review entirely. The malicious change happens after the review. Hardening practices here include running each build job in a fresh ephemeral environment (so no residual state from a previous job can be exploited), limiting the secrets each job can access to only what it needs, and pinning CI plugins to full commit hashes rather than mutable version tags.

Over-permissioned credentials. Supply chain attacks frequently exploit service accounts or CI tokens that have broader access than any single task requires. Least privilege means scoping every credential to its specific task: a build job that pushes an image to a registry should not also be able to modify branch protection rules or access production infrastructure. CISA specifically recommends phishing-resistant multi-factor authentication on all developer and CI/CD accounts.

Unverified registry content. Without admission controls, a developer can pull any image from any public registry and use it as a base—extending the supply chain to every maintainer of every image they touch. Registry access policies that restrict pulls to verified publishers, and deployment admission controllers that enforce signature verification, contain this exposure.

Runtime Is Where the Others Fall Short

All the controls above are applied before or at the point of deployment. Runtime monitoring addresses what happens when something gets through anyway.

Static scanning and build-time analysis catch the threats that were known and visible at the time of the scan. They do not catch a compromised dependency that behaves normally during testing but activates malicious behavior under specific production conditions—a time-delayed payload, a configuration-triggered exfiltration, or behavior that only surfaces under real traffic patterns.

Runtime monitoring for supply chain security means more than watching for known-bad signatures. It requires building baseline behavioral profiles for container workloads—what network connections they normally make, which file paths they read or write, which processes they spawn—and alerting when observed behavior diverges from that baseline. An unexpected outbound connection from a container that has no reason to make external calls is a meaningful signal, even if no scanner ever flagged the underlying code.

Building the Program Incrementally

For teams with no existing supply chain security program, the practical path is incremental rather than all-at-once. Starting with base image selection and dependency pinning addresses the highest-leverage risks with relatively low implementation overhead. From there, adding SBOM generation at every build and signed provenance attestations for CI jobs builds the visibility layer that makes everything else possible.

Policy enforcement, developer-integrated vulnerability scanning, and runtime behavioral monitoring can follow as the program matures. The point is not to reach a particular maturity level on a particular timeline, but to close the most exposed gaps first and avoid the common trap of treating a single tool or a periodic audit as a substitute for the full chain of controls.

The key principle underlying all of it is straightforward: trust is not something you establish once at the start of a delivery pipeline and then assume throughout. Every stage that handles your software—from the registry that served your base image to the build system that compiled it to the runtime that executes it—is a place where that trust either gets verified or gets assumed. The difference between those two choices is where most supply chain compromises find their opening.

Sources

  1. How Common Are Malicious Packages in Open-Source Registries?
  2. Provenance
  3. 5 Software Supply Chain Security Best Practices | Docker
Scroll to Top