What a Software Supply Chain Attack Is
Your software doesn't exist in isolation. It depends on compilers, build tools, CI/CD systems, package registries, third-party libraries, and update mechanisms. Each of these is a link in your supply chain β and each is a potential attack vector.
A supply chain attack targets one of these upstream dependencies rather than your code directly. The attacker compromises something you trust, then your trust relationship does the rest. The malicious code arrives wearing legitimate credentials, signed by a trusted key, distributed through a channel you've whitelisted.
Why it's so effective: Supply chain attacks subvert the assumptions your security controls are built on. Your antivirus trusts signed software. Your firewall allows connections to npm. Your CI/CD pulls from authorised registries. The attack doesn't need to defeat any of these β it rides through them.
The SolarWinds Attack: Backdoored Updates at Scale
In late 2020, it emerged that attackers (later attributed to the Russian SVR intelligence agency) had compromised the build system of SolarWinds, a network monitoring company. The attackers injected a backdoor β named SUNBURST β into the legitimate Orion software update mechanism. The malicious update was cryptographically signed with SolarWinds' legitimate certificate and distributed to roughly 18,000 customers through the normal update channel.
The victims included the US Treasury, Department of Justice, Department of Homeland Security, and hundreds of Fortune 500 companies. The malware was present in their environments for months before discovery. Many organisations didn't know they were affected until months after the initial disclosure.
The build system as attack surface: SolarWinds' build pipeline was the entry point. The attackers modified the build process itself β so the source code was clean, but the compiled binary that went out to customers contained the backdoor. Source code scanning would not have caught it.
Log4Shell: When a Logging Library Caused Global Panic
CVE-2021-44228 β Log4Shell β was disclosed in December 2021 in Log4j, a Java logging library used by virtually every Java application. The vulnerability allowed remote code execution through a single crafted log message. An attacker who could get a Java application to log a string they controlled could execute arbitrary code on the server.
The scope was staggering. Log4j is a dependency β direct or transitive β in an enormous fraction of the Java ecosystem: Minecraft servers, enterprise software, government systems, cloud services, industrial control systems. Organisations spent weeks auditing which of their systems were affected.
The transitive dependency problem: Many organisations discovered they were running Log4j in systems they didn't know used Java. The library was a transitive dependency β a dependency of a dependency β invisible without a Software Bill of Materials.
Dependency Confusion Attacks
In 2021, security researcher Alex Birsan demonstrated a novel attack technique: uploading malicious packages to public registries (npm, PyPI) with the same names as internal private packages used by major tech companies.
When a developer ran npm install, the package manager sometimes chose the public malicious version over the intended private one β because public registries had higher version numbers or priority. Birsan earned over $130,000 in bug bounties from Apple, Microsoft, PayPal, and others using this technique.
// Company's internal package β exists in private registry { "dependencies": { "@acmecorp/internal-auth": "^2.1.0" } } // Attacker publishes acmecorp-internal-auth (no scope) to npm // with version 3.0.0 β higher than internal version. // npm pulls the public malicious version instead.
Mitigation: Scope private packages consistently (@yourcompany/ prefix), configure your package manager to only fetch scoped packages from your private registry, and pin exact versions with hash verification.
Transitive Dependencies: The Invisible Risk
Your package.json might list 30 direct dependencies. But those 30 packages have their own dependencies β and those have dependencies too. A typical Node.js project can have hundreds or thousands of transitive dependencies, most of which the development team has never heard of.
The left-pad incident (2016) demonstrated this: a developer unpublished an 11-line utility package from npm, and thousands of builds broke because major projects transitively depended on it. The same mechanism applies to malicious packages β one compromised transitive dependency can affect everyone downstream.
SCA tools see transitive dependencies: Software Composition Analysis tools resolve the full dependency tree and check every package β direct and transitive β against vulnerability databases. This is the only practical way to know what you're actually running.
SBOM: Software Bill of Materials
An SBOM is a formal, machine-readable inventory of all components in a software product β including all direct and transitive dependencies, their versions, their licenses, and their provenance. It's the equivalent of a nutrition label for software.
Following executive orders in the US and regulations in the EU (Cyber Resilience Act), SBOMs are becoming a compliance requirement for software sold to governments and regulated industries. But compliance aside, an SBOM is genuinely useful: it's the document that tells you in minutes whether you're affected when a new CVE drops.
# Generate SBOM in CycloneDX format pip install cyclonedx-bom cyclonedx-py --format json --output sbom.json # Or for Node.js npx @cyclonedx/cyclonedx-npm --output-file sbom.json # Then check against vulnerability databases grype sbom:sbom.json
Detecting Malicious Packages Before They Hit Production
Traditional SCA compares package versions against a CVE database. Malicious packages present a harder problem β they may be new, with no CVE assigned yet. Detection requires additional signals:
- Behaviour analysis: Does the package make network requests on install? Does it access environment variables or files outside its declared scope?
- Reputation signals: New packages with high download velocity, packages from newly-created accounts, packages with mismatched metadata
- Code similarity: Packages that closely resemble popular packages with slight name differences (typosquatting)
- Lifecycle checks: Packages whose maintainers have changed recently or whose source repository has been deleted
Dependency Pinning and Verification
Pinning to exact versions is necessary but not sufficient β an attacker can republish a new version of a package under the same version number on some registries. Hash-based pinning ties your dependency to a specific content hash, so any modification β even a single character β fails verification.
// npm lock file pins exact content hash "express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", "integrity": "sha512-5/PsL6iGPdfQ/..." // If the published package changes, integrity check fails }
Commit your lock files to version control. Never run npm install without a lock file in CI. Use npm ci instead of npm install in pipelines β it enforces lock file integrity.
What to Do Right Now
- Run SCA immediately β find CVEs in your current dependencies. Many teams discover critical-severity issues they've been running for months.
- Generate an SBOM β know what you're running. Without this, every new CVE requires manual research.
- Commit lock files β ensure lock files exist and are committed for all projects.
- Switch to
npm ci/pip install --require-hashesin CI pipelines. - Review CI/CD pipeline security β restrict what can run in your build environment, pin GitHub Actions to specific commit SHAs.
- Monitor for new CVEs β subscribe to advisories for your key dependencies. Set up automated scanning that alerts on new findings.
- Evaluate private registry use β consider running a private registry mirror that you control rather than fetching directly from public registries.
Scan Your Dependencies for Supply Chain Risks
AquilaX SCA scans your full dependency tree β direct and transitive β for CVEs, malicious packages, and licence issues across all major ecosystems.
Start Free Scan