The software your organization depends on did not originate entirely in-house. It pulls from open source packages, commercial SDKs, third-party APIs, cloud-based CI/CD runners, and update mechanisms managed by vendors you have never audited. Every one of those dependencies is a link in your supply chain. Attackers have noticed, and they have been exploiting those links with increasing sophistication and patience.
Supply chain attacks are not new — the concept predates modern computing — but the scale of exposure has changed dramatically. A single poisoned package on npm or PyPI can reach millions of downstream systems before anyone notices. A backdoor inserted into a widely-used build tool can survive for months inside environments that otherwise have excellent perimeter defenses. Understanding how these attacks work, where they hide, and how to reduce your exposure is no longer optional for security practitioners.
What Is a Software Supply Chain Attack?
A software supply chain attack occurs when an adversary tampers with software or the processes used to build, distribute, or update it — targeting downstream consumers rather than attacking them directly. Instead of compromising your network, the attacker compromises something you willingly pull into your network.
The supply chain includes a wide surface area. Source code repositories, package managers, build pipelines, signing infrastructure, update servers, and even developer workstations are all in scope. Any point in that chain where trust is extended without verification becomes a potential insertion point for malicious code.
NIST defines supply chain risk management (C-SCRM) under SP 800-161r1, which provides a framework for identifying, assessing, and responding to cybersecurity risks throughout the supply chain. It is one of the foundational documents for organizations building supply chain security programs.
What makes supply chain attacks particularly dangerous is the exploitation of trust. Security controls that would flag an unknown external connection may raise no alert at all when the threat arrives as a signed software update from a recognized vendor or as a dependency your own developers installed last quarter.
Primary Attack Vectors
Compromised Build Environments
The SolarWinds attack — disclosed in December 2020 and attributed to the Russian SVR-linked group Cozy Bear — remains the defining case study for this vector. Attackers gained access to SolarWinds' build environment and injected malicious code into the Orion software update process. The resulting trojanized updates were digitally signed by SolarWinds and delivered to roughly 18,000 organizations, including multiple U.S. federal agencies. The malware, known as SUNBURST, lay dormant for up to two weeks before activating, specifically to evade sandbox analysis that typically runs over shorter observation windows.
The SolarWinds intrusion highlighted a fundamental gap: organizations extensively verify external code but rarely scrutinize software updates from trusted vendors at the same level. — CISA Advisory AA20-352A
Malicious or Typosquatted Packages
Package registries like npm, PyPI, RubyGems, and NuGet operate on a publish-first model where anyone can submit packages with minimal vetting. Attackers exploit this in two ways. The first is typosquatting — registering packages with names nearly identical to popular libraries (e.g., reqeusts instead of requests) and waiting for developers to mistype a dependency name. The second is direct compromise of legitimate package maintainer accounts, allowing attackers to push malicious versions of real, widely-trusted packages.
In 2022, several npm packages belonging to a single maintainer were compromised after the maintainer's account credentials were stolen. Because those packages had hundreds of thousands of weekly downloads, the attack propagated rapidly before npm pulled the affected versions. The malicious code contained an environment variable harvester designed to extract tokens and credentials from CI/CD environments.
Dependency Confusion
Security researcher Alex Birsan demonstrated this technique in 2021, earning bug bounties from over 35 major companies including Apple, Microsoft, and PayPal. The attack exploits the behavior of package managers that query public registries before internal ones when a package name is specified without a scope or registry prefix. An attacker identifies internal package names — often visible in public build scripts, job postings, or error messages — and publishes public packages with the same names but higher version numbers. The package manager then fetches the attacker's public package instead of the legitimate internal one.
# How dependency confusion manifests in a package.json
# Internal package: @acme/auth-utils (published to private registry)
# Attacker publishes: auth-utils (no scope) to npm with version 9.0.0
# If package manager checks npm first and finds higher version, it wins
npm install auth-utils
# Resolves to attacker's package if scoping is not enforced
CI/CD Pipeline Compromise
Continuous integration and continuous delivery pipelines have become high-value targets because they sit at the intersection of source code, credentials, and deployment infrastructure. Compromising a GitHub Actions workflow, a Jenkins server, or a CircleCI environment can give an attacker the ability to exfiltrate secrets, inject code into builds, or push tampered artifacts to production without ever touching the application code directly.
In January 2023, CircleCI disclosed a security incident in which attackers had compromised an employee's device and stolen session tokens, ultimately gaining access to customer environment variables, tokens, and keys stored in CircleCI. Organizations that rotated all secrets stored in CircleCI immediately were advised to do so regardless of whether they saw evidence of compromise.
Open Source Maintainer Compromise
The XZ Utils backdoor, discovered in March 2024, is the supply chain attack that alarmed the security community more than any other in recent memory. A threat actor operating under the identity "Jia Tan" spent roughly two years building trust within the XZ Utils open source project — contributing legitimate code, building a reputation as a reliable maintainer, and gradually taking on more responsibility. Once trusted with commit access, the attacker inserted a highly sophisticated backdoor targeting the liblzma library, which is linked into sshd on several Linux distributions through systemd. Had it not been caught by a Microsoft engineer who noticed unexpected CPU usage in SSH, the backdoor would have enabled unauthenticated remote code execution on any affected system running a vulnerable version of OpenSSH.
The XZ Utils case (CVE-2024-3094) demonstrated that nation-state actors are willing to invest years of effort into establishing trusted identities within the open source community. The attacker displayed sophisticated understanding of both the codebase and the social dynamics of open source maintainership. Traditional technical controls alone cannot defend against this threat model.
Why Detection Is Hard
Supply chain attacks succeed in part because they are engineered to look like normal operations. Malicious code arrives via the same channels as legitimate code. Updates are signed with valid certificates. Dependencies come from trusted registries. The attacker has done the work of appearing legitimate before the payload is ever delivered.
Several factors compound the detection problem. Organizations rarely audit transitive dependencies — the dependencies of their dependencies — which can number in the thousands for even a moderately complex application. Many security teams have limited visibility into the build pipeline itself, treating it as a development concern rather than a security one. And the gap between when malicious code is introduced and when it activates (as demonstrated by SUNBURST's dormancy period) means behavioral detection often fires too late or not at all.
The average enterprise application has over 500 open source dependencies. Each dependency introduces its own dependency tree. The total number of packages a single application implicitly trusts can exceed 10,000. Auditing this manually is not feasible — automation and policy enforcement are required.
Defensive Controls and Best Practices
Software Bill of Materials (SBOM)
An SBOM is a formal, machine-readable record of every component in a software product, including libraries, frameworks, and their versions. The May 2021 U.S. Executive Order on Improving the Nation's Cybersecurity (EO 14028) mandated that software vendors providing products to the federal government produce SBOMs. When a new vulnerability is disclosed, organizations with comprehensive SBOMs can immediately query which of their systems are affected rather than spending days inventorying manually.
Two dominant SBOM formats have emerged: SPDX (Software Package Data Exchange), maintained by the Linux Foundation, and CycloneDX, maintained by OWASP. Both are supported by a growing ecosystem of generation and analysis tools.
Dependency Pinning and Lock Files
Specifying exact dependency versions — rather than accepting any version within a semver range — prevents package managers from silently upgrading to a compromised newer release. Lock files (package-lock.json, Pipfile.lock, Gemfile.lock) capture the exact resolved dependency tree and should be committed to version control and treated as security artifacts. Combined with integrity hashes, lock files allow build systems to verify that installed packages match exactly what was last reviewed.
# Verify npm package integrity using lock file hashes
npm ci # Uses package-lock.json, fails if tree has changed
npm audit # Checks against known vulnerability database
# Pin Python dependencies with hashes
pip install --require-hashes -r requirements.txt
Artifact Signing and Verification
Code signing establishes a cryptographic chain of custody from the source code commit to the deployed artifact. Sigstore — a free, open source project backed by the OpenSSF and supported by Google, Red Hat, and Purdue University — provides a certificate authority and transparency log specifically designed for software signing. The cosign tool from Sigstore allows container images and other artifacts to be signed at build time and verified before deployment.
Supply chain Levels for Software Artifacts (SLSA, pronounced "salsa") is a security framework that defines four integrity levels for build pipelines, covering provenance generation, isolation of build environments, and auditability of the entire process. Achieving SLSA Level 3 or higher requires that builds be run in an isolated, ephemeral environment and that provenance be automatically generated and signed by the build system.
Private Registry Mirroring and Scoping
Running an internal package registry (Artifactory, Nexus, GitHub Packages, or similar) that proxies approved external packages eliminates the direct dependency on public registries at build time. Combining this with namespace scoping — requiring all internal packages to use a specific registry scope — closes the dependency confusion attack surface. Package manager configuration should enforce that scoped packages always resolve to the internal registry, not public ones.
CI/CD Hardening
Pipeline security has several distinct dimensions. Secrets should never be stored in code or passed as plaintext environment variables — use a secrets manager integrated with your pipeline (HashiCorp Vault, AWS Secrets Manager, GitHub Actions secrets with OIDC). Pipeline definitions themselves should be version-controlled and subject to code review. Third-party GitHub Actions or other pipeline plugins should be pinned to a specific commit SHA rather than a mutable tag, since tag references can be moved by maintainers or attackers.
# Insecure: tag can be moved to point at malicious commit
- uses: actions/checkout@v3
# Secure: pinned to immutable commit SHA
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
Vendor Risk Assessment and Update Hygiene
For commercial software vendors, supply chain risk cannot be fully eliminated through technical controls alone. Due diligence should include asking vendors about their secure software development lifecycle (SSDLC), whether they produce SBOMs for their products, how they handle security incidents involving their build infrastructure, and whether they support update integrity verification. When evaluating software updates, organizations in critical sectors should consider a brief validation period before mass deployment — particularly for updates that include binary changes to core components.
The Regulatory Landscape
Supply chain security has moved from a best-practice recommendation to a compliance requirement in several frameworks. EO 14028 established SBOM requirements and directed NIST to publish guidance on secure software development practices, resulting in the NIST Secure Software Development Framework (SSDF), SP 800-218. The EU Cyber Resilience Act, which entered into force in November 2024, includes provisions requiring manufacturers of products with digital elements to address supply chain security and vulnerability disclosure throughout the product lifecycle.
For organizations operating in regulated industries, DORA (Digital Operational Resilience Act) in the EU financial sector explicitly addresses ICT third-party risk, including software supply chain dependencies, with requirements for contractual provisions, monitoring, and incident reporting.
Key Takeaways
- Trust is the attack surface. Supply chain attacks succeed because they exploit the trust extended to vendors, maintainers, and registries. Every point where trust is granted without verification is a potential entry point.
- Inventory before you can defend. An SBOM is not just a compliance checkbox — it is the foundation for knowing what you are running. Without it, you cannot assess exposure when a new vulnerability is disclosed.
- Harden your pipeline, not just your perimeter. CI/CD environments hold credentials, build secrets, and deployment access. Treat them with the same security rigor as production systems: least privilege, secret rotation, and commit-pinned third-party actions.
- Dependency hygiene is an ongoing practice. Pin versions, use lock files with integrity hashes, audit transitive dependencies regularly, and consider running your own registry proxy to control what packages enter your build environment.
- Nation-state actors play a long game. The XZ Utils incident proved that sophisticated threat actors will invest years building legitimate reputations in open source communities. Automated technical controls are necessary but not sufficient — maintainer vetting and community vigilance matter.
The software supply chain is not a new problem, but the scale and sophistication of attacks targeting it have changed the calculus for defenders. Organizations that treat supply chain security as a distinct risk domain — with dedicated controls, regular audits, and clear ownership — are significantly better positioned than those treating it as a subset of general patch management. The dependency graph of modern software is vast, and attackers are counting on organizations not having mapped it.