Software Supply Chain

Software Supply Chain Attacks: How Trusted Dependencies Become a Security Risk

Learn how software supply chain attacks compromise dependencies, build systems and release pipelines, plus practical controls for reducing the risk.

Software Supply ChainApplication SecurityDependenciesDevSecOpsSBOM
Software Supply Chain Attacks: How Trusted Dependencies Become a Security Risk article cover

A modern application is rarely built from code written by one team. It may depend on hundreds of open-source packages, container images, build actions, package registries, CI/CD services, compilers, signing systems and third-party update channels. That speed and reuse are valuable, but they also create a larger trust boundary.

A software supply chain attack targets one of those upstream components or processes so that malicious or unauthorized changes reach downstream users through something they expected to trust. The attacker may not need to compromise the final application directly. If they can alter a dependency, build environment, artifact or update mechanism, the normal delivery process can become the attack path.

NIST’s Secure Software Development Framework treats protection of software components, development environments and release integrity as part of secure software development. The SLSA framework focuses specifically on artifact integrity and verifiable provenance across software supply chains. CISA also recommends using Software Bills of Materials (SBOMs) to improve visibility into software components and dependencies.

The core lesson is simple: trust should be based on verifiable controls, not merely on the fact that a package, build job or update came through a familiar channel.

Software supply chain attack path showing source, dependency, build, artifact and deployment trust boundaries

What counts as the software supply chain?

The software supply chain includes everything that can influence the software that finally runs in production or on a user’s device. That is much broader than the source repository.

A typical chain can include:

  • first-party source code and configuration;
  • open-source and commercial dependencies;
  • package managers and registries;
  • build scripts, CI/CD workflows and reusable actions;
  • compilers, container builders and other tooling;
  • build runners and hosted build platforms;
  • artifact repositories and container registries;
  • code-signing keys and release credentials;
  • deployment systems and software update channels.

If any important stage can alter the final artifact, that stage belongs in the threat model.

This is why supply chain security is not the same as dependency scanning. A project can have no known vulnerable package and still be exposed if an attacker can tamper with its build process or replace a release artifact. The same principle appears in security misconfiguration: secure components can still become unsafe when the surrounding environment or permissions are weak.

How does a software supply chain attack work?

The attacker looks for a point where one compromise can influence many downstream systems.

Consider a simplified application that depends on an external package. The development team reviews its own code carefully, but its build automatically downloads the newest allowed version of that package. If the package maintainer’s publishing account is compromised, or if a malicious package is accepted through a weak dependency process, the build can import attacker-controlled code without any change to the application’s own repository.

Another attack path targets the build environment. The source code may be completely legitimate, but a compromised build runner can alter the compiled output. Unless the organisation can verify how the artifact was produced, reviewers may see clean source while users receive a different binary.

A third path targets release and update infrastructure. If an attacker obtains a signing credential or gains control over an artifact repository, they may be able to distribute a modified release through the same channel customers normally trust.

These scenarios are different technically, but they share the same security failure: the organisation cannot reliably prove that the artifact being consumed is the intended output of an authorized process.

The main attack paths

1. Malicious or compromised dependencies

Dependencies save development time, but they also import external trust. Risk can enter through a package that was malicious from the beginning, a legitimate package whose maintainer account was compromised, a dependency that was abandoned and later taken over, or a package name designed to trick developers into installing the wrong component.

The risk also extends to transitive dependencies. A developer may select one package directly while that package automatically installs several others. The security boundary therefore includes dependencies several layers below the package named in the application’s manifest.

A lockfile helps by recording exact resolved versions, but it is not a complete security control. It improves reproducibility, yet a locked malicious artifact is still malicious. Teams also need source trust, review, vulnerability and malware intelligence, integrity verification, and controlled update decisions. For a broader explanation of malicious software behavior itself, see What Is Malware?.

2. Source repository compromise

If attackers gain write access to a source repository, they may add malicious code, modify build scripts or weaken security checks. Strong authentication, protected branches, required review and least-privilege repository permissions reduce this risk.

The important point is that review rules must apply to files that influence the build, not just application source. A tiny change to a CI workflow can sometimes be as security-sensitive as a large change to production code.

3. Build system compromise

The build system converts source into artifacts. That makes it one of the most sensitive trust boundaries in the chain.

A compromised runner, build image, plugin or reusable workflow can inject code after source review. This is one reason SLSA provenance matters: provenance provides verifiable information describing where, when and how an artifact was produced.

Provenance does not magically make software safe. It gives consumers and security controls evidence they can verify. That evidence becomes more useful when the build process itself is isolated, repeatable and protected against unauthorized modification.

4. Artifact or registry tampering

After a successful build, organizations often store packages, binaries or container images in a registry. If an attacker can overwrite, replace or redirect those artifacts, downstream systems may consume something different from what the build originally produced.

Content digests, immutable artifact versions, signatures and restricted publishing permissions can make unauthorized replacement harder and easier to detect.

For containers, pinning an image by immutable digest provides stronger identity than relying only on a mutable tag such as latest. A tag is convenient for humans, but a digest identifies specific content.

5. Release credential or signing-key theft

Code signing can provide strong assurance that a release was authorized by a holder of a signing key. But that assurance depends on protecting the key and the signing process.

If a signing credential is stolen, an attacker may be able to make malicious software appear legitimately signed. High-value release credentials should therefore use strong access controls, short-lived credentials where practical, isolated signing workflows, audit logging and secure key storage.

Vulnerable dependency vs supply chain compromise

These concepts are related but not identical.

Situation What went wrong? Typical security response
A dependency contains an accidental vulnerability A software defect creates exploitable behavior Patch or replace the component, assess exposure, test the update
A dependency release is deliberately malicious The upstream component itself is part of the attack Quarantine the version, investigate compromise, rotate affected credentials, review downstream exposure
A clean source tree produces a modified artifact Build or release infrastructure was tampered with Stop releases, verify provenance, rebuild from trusted infrastructure, investigate the build environment
A registry serves a different artifact under a trusted name Distribution integrity failed Verify digest/signature, restore trusted artifact, review registry access and publishing controls

A vulnerability scanner is very useful for the first row. It is not enough for the other three. Supply chain defence needs integrity, provenance and identity controls in addition to vulnerability management.

What an SBOM can and cannot do

A Software Bill of Materials is an inventory of software components and their relationships. CISA describes the SBOM as a key building block for software security and supply chain risk management because it helps consumers understand which components are present.

That visibility becomes valuable during incident response. If a dependency is later found to be vulnerable or malicious, an organisation with reliable component inventories can ask a much more practical question: which of our applications actually contain it?

An SBOM is not proof that every component is trustworthy. It also does not prove that the final binary was built from the listed source. Think of it as visibility, not attestation.

For stronger assurance, combine SBOM data with provenance, signatures, build controls and dependency policy.

A practical secure dependency workflow

A small team does not need a complex enterprise platform to improve supply chain security. The workflow can start with a few disciplined controls.

Before adding a new dependency

Ask why the dependency is needed and what privilege it will have. A tiny formatting library and a package that executes during installation do not have the same risk.

Review the project’s official source and package identity. Check whether it is actively maintained, whether releases are traceable to the expected project, and whether the package manager is resolving the intended name.

Prefer fewer dependencies when functionality is simple enough to implement safely in-house. This is not an argument against open source. It is an argument against importing unnecessary trust.

During installation and builds

Commit dependency manifests and lockfiles. Use automated dependency review on pull requests and alert on unexpected additions or major version changes.

Where the ecosystem supports it, verify package integrity hashes or signatures. Restrict install-time scripts when they are unnecessary, because installation hooks can execute code before the application itself runs.

Pin build actions and container base images to immutable identifiers for security-sensitive workflows. Review changes to CI/CD configuration with the same care as production code.

Before release

Generate an SBOM from the actual build where practical. Record the source revision, dependency snapshot and build identity associated with the release.

Produce provenance or equivalent attestations when your build platform supports it. Sign artifacts through a controlled release process. Keep the release pipeline separate from ordinary developer credentials so one compromised workstation does not automatically become a production signing authority.

During deployment

Verify the artifact you are deploying. A secure build is wasted if the deployment system accepts any artifact carrying a familiar filename.

For example, a container deployment policy can require an approved registry and an immutable image digest:

image:
  repository: registry.example.com/payments-api
  digest: sha256:<approved-build-digest>

The placeholder digest above is intentionally not a real artifact. In production, the deployment process should obtain the digest from the verified build output, not from a manually copied chat message or ticket.

Why provenance matters

SLSA defines provenance as verifiable information about where, when and how an artifact was produced. That solves a specific security problem: source review alone cannot tell you whether the artifact was actually created from that source in the expected environment.

Imagine two binaries with the same filename. One was built by the approved CI workflow from the reviewed commit. The other was compiled on an unknown laptop from modified source. If the organisation does not verify provenance or another trustworthy build record, those files may look operationally equivalent.

A strong release process connects four identities:

  1. the source revision;
  2. the build process;
  3. the resulting artifact digest;
  4. the authorized release decision.

That chain of evidence makes silent substitution much harder.

Protect the CI/CD system as production infrastructure

Development pipelines often hold powerful credentials: registry tokens, cloud deployment credentials, signing access and repository write permissions. Treating CI/CD as a low-risk developer convenience is a mistake.

Useful controls include least-privilege job permissions, short-lived workload identities, protected secrets, isolated runners for sensitive builds, restricted third-party actions, branch protection, mandatory review for workflow changes and detailed audit logs.

Do not expose long-lived production secrets to pull requests from untrusted forks. Build systems should assume that code being tested can be hostile until it has crossed an appropriate trust boundary. The same general trust-boundary thinking is useful when reviewing data poisoning in AI systems: inputs that influence downstream behavior need controlled provenance and authorization.

Dependency updates should be controlled, not avoided

Freezing dependencies forever is not a safe supply chain strategy. Old packages can accumulate known vulnerabilities and compatibility problems. The goal is to make updates observable and reviewable.

A useful pattern is to let automation propose updates while requiring tests and policy checks before merge. High-risk changes can receive manual review. Emergency security updates can move quickly through the same controlled process rather than bypassing it completely.

For critical environments, organizations may also use an internal package proxy or allowlist so production builds do not retrieve arbitrary packages directly from the public internet.

What to do if you suspect a supply chain compromise

First, stop the affected release or deployment path if doing so is operationally safe. Preserve evidence before rebuilding everything.

Identify the earliest trusted point in the chain. Was the source repository clean? Was the build environment trustworthy? Does the artifact digest match the expected build? Which dependencies and build actions were present? Which credentials could the compromised stage access?

Then scope downstream exposure. SBOMs, artifact inventories and deployment records can help identify which systems consumed the affected component.

Rotate credentials that the compromised software or pipeline could access, not merely the credential initially suspected. Rebuild from a known-trusted source and environment, regenerate attestations, and retest before restoring distribution.

The recovery target is not simply “a clean file.” It is a restored chain of trust from source to release.

Common mistakes

One common mistake is focusing only on known CVEs. A deliberately malicious package may have no CVE at all.

Another is trusting package names rather than identities and content. Names are human-friendly labels. Security-sensitive automation should verify immutable versions, hashes, digests, signatures or provenance when the ecosystem supports them.

A third mistake is generating an SBOM and treating the job as finished. An inventory is useful only when teams can connect it to vulnerability response, dependency review and real deployed artifacts.

Finally, many teams secure production infrastructure much more carefully than their build infrastructure even though the build pipeline can produce everything production later executes.

A practical security model

Software supply chain security becomes easier to reason about when every stage answers three questions:

Who is allowed to change this stage? Use strong identity, least privilege and protected change processes.

Can we prove what went in and what came out? Use version control, immutable identifiers, hashes, SBOMs and provenance.

Can an unexpected change be detected before it reaches users? Use review, policy enforcement, isolated builds, artifact verification and monitoring.

No single control makes the software supply chain trustworthy. The goal is layered evidence so that compromising one account, package or service does not silently rewrite the entire path from source to production.

That is the difference between assuming a dependency is trusted and being able to explain why a particular artifact deserves trust.

Sources and further reading