A03:2025 — NEW

Software Supply Chain Failures

A brand-new category in OWASP Top 10:2025, reflecting how modern attacks increasingly target the ecosystem around your code rather than your code itself. When an attacker compromises one upstream package, they inherit access to every application that depends on it.

Why it matters

The SolarWinds attack reached 18,000 organizations through a single poisoned build. The xz backdoor (CVE-2024-3094) spent two years being quietly planted in a core Linux utility before discovery. A single malicious npm package can be running inside millions of Node.js applications within hours of publication.

Supply chain attacks are so effective because they exploit trust — the trust you've placed in your dependencies, your build tools, and your deployment pipeline.

What is a software supply chain?

Your application doesn't run in isolation. It depends on open-source libraries, internal packages, container base images, build scripts, CI/CD tools, and cloud infrastructure. All of that — from the first npm install to the final deployment artifact — is your software supply chain.

A supply chain attack happens when an adversary inserts malicious code or behavior into any link in that chain, so that the compromise flows downstream to you automatically. You write perfectly secure code, but the library you imported three levels deep has been backdoored. Your pipeline pulls a container image with a hidden crypto miner. A typo in a package name installs an attacker-controlled package instead of the one you intended.

This is fundamentally different from targeting your application directly. The attacker doesn't need to find a vulnerability in your code. They need to find a vulnerability in your trust.

Why did OWASP add this in 2025?

Software supply chain compromises have always existed, but the frequency and scale of incidents escalated sharply in the early 2020s. OWASP's previous lists captured some of this under "Using Components with Known Vulnerabilities" (A06:2021), but that category focused on known, patched vulnerabilities in legitimate packages. It didn't capture the broader threat model: actively malicious packages, compromised build infrastructure, and intentional backdoors in trusted software.

The 2025 edition makes the distinction explicit. A03 covers the full lifecycle of supply chain risk, from the libraries you pull in to the build system that assembles your artifacts.

Types of supply chain attacks

Dependency confusion attacks

In 2021, security researcher Alex Birsan demonstrated that you could publish a public package with the same name as a private internal package used by Apple, Microsoft, Tesla, and dozens of other companies. Package managers like npm, pip, and RubyGems would pull the public version by default in certain configurations — even though the company intended to use their internal one. Birsan earned over $130,000 in bug bounty payouts from the affected companies.

The attack works because many package managers search public registries before (or instead of) private ones. Unless you explicitly pin to a private registry, a public package with a higher version number can silently win.

Typosquatting

Publish colourama and wait for developers to mistype colorama. Publish reqeusts instead of requests. This is a numbers game — with tens of millions of package installations happening daily, even a low typo rate means thousands of installs of your malicious package.

The npm ecosystem has been particularly hit by this. Over the years, packages like crossenv, nodemailer-js, nodemailr, and hundreds of others have been published specifically to catch typos of popular packages. Most are discovered within days, but the damage window is real.

Compromised legitimate packages: the event-stream attack

In 2018, a package called event-stream — downloaded 1.5 million times per week at its peak — was transferred to a new maintainer. The new maintainer added a dependency called flatmap-stream, which contained an encrypted payload that only activated when run in the environment of a specific cryptocurrency wallet application (Copay). The payload would intercept private keys and harvest bitcoins from users with wallets holding more than 100 BTC.

The attacker targeted the original maintainer directly — offering to "help maintain" the abandoned package — waited for trust to build, then struck. The malicious code was live for 59 days before discovery. This is a sophisticated social engineering attack against the open-source maintainer as a vector, not against the code itself.

The xz backdoor (CVE-2024-3094)

This is the most sophisticated supply chain attack publicly documented. An account named "Jia Tan" began contributing to the xz compression library — a core dependency in essentially every Linux system — in 2021. Over two years, Jia Tan built up credibility through genuine, useful contributions. They helped triage issues, reviewed pull requests, and eventually convinced the maintainer to give them commit access.

In early 2024, Jia Tan committed code that introduced a backdoor into the xz build system. The malicious code was hidden inside binary test files (not in the readable source) and was designed to inject a payload into the liblzma library. That library is linked by systemd in many Linux distributions, meaning the backdoor would give the attacker SSH access to any affected machine.

The backdoor was discovered almost by accident. Andres Freund, a Microsoft engineer, noticed that SSH logins on his Debian system were slightly slower than expected. He investigated, found the anomaly in xz, and published his findings. The attack was caught before it reached stable distributions, but the implication was chilling: a multi-year, patient, well-resourced operation targeting Linux infrastructure at a fundamental level.

CVE-2024-3094 was assigned a CVSS score of 10.0.

SolarWinds Orion (SUNBURST)

In 2020, attackers (later attributed to Russian intelligence) compromised the build environment of SolarWinds Orion, an IT monitoring platform used by government agencies and Fortune 500 companies. The attackers inserted a backdoor called SUNBURST into the Orion software update mechanism. The trojanized update was signed with SolarWinds' legitimate certificate and distributed to approximately 18,000 customers.

The attack lay dormant for up to two weeks after installation to evade sandbox analysis, then communicated with C2 infrastructure disguised as legitimate Orion traffic. Victims included the US Treasury, Department of Homeland Security, and numerous technology companies. The attackers had access for months before discovery.

What makes SolarWinds a defining supply chain incident is the vector: not the product's code, but the build system that compiled and signed the product. The source code was clean. The attacker modified the build process itself.

ua-parser-js: a triple compromise

In October 2021, the npm package ua-parser-js — used by Facebook, Microsoft, Amazon, and downloaded 8+ million times per week — was hijacked. The attacker published three malicious versions in rapid succession (0.7.29, 0.8.0, 1.0.0). Each version installed a crypto miner (jsextension) on Linux/Mac and a password stealer on Windows, using postinstall scripts.

The attack lasted only a few hours before npm removed the packages and the maintainer regained control. But in those hours, the malicious versions were pulled into builds across the world. This incident prompted npm to introduce enhanced security measures including package publishing notifications and suspicious activity detection.

CI/CD pipeline attacks

Your CI/CD system is an extraordinarily powerful position. It typically has access to production secrets, cloud credentials, private repositories, and deployment keys. Attackers who can inject code into your build pipeline can exfiltrate these secrets or modify your build artifacts before deployment.

Common CI/CD attack vectors include:

Malicious container base images

Docker Hub and other registries host millions of container images. Attackers publish images with names similar to official ones — ngix, alpine-ssl, ubuntu-20-04 — and developers pull them without verifying the source. Container images also pull dependencies during their own build, introducing a nested supply chain problem.

How to detect supply chain issues in your application

Check your dependency tree

The attack surface is rarely the direct dependency you added. It's the transitive dependency three levels deep that nobody audited.

# npm — full tree
npm ls --all

# Check for known vulnerabilities
npm audit

# Python
pip-audit

# See exact installed versions vs what you specified
npm list --depth=0

Look for suspicious package metadata

When evaluating a dependency, look beyond the name:

Verify subresource integrity on CDN-loaded assets

If your application loads JavaScript or CSS from a CDN, that CDN is part of your supply chain. Use Subresource Integrity (SRI) hashes:

<script
  src="https://cdn.example.com/lib/jquery-3.6.0.min.js"
  integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK"
  crossorigin="anonymous"></script>

Without the integrity attribute, if the CDN is compromised or the file is updated, your users run whatever is there. Most automatic scanning tools will flag missing SRI hashes on third-party script loads.

Pin dependencies to exact versions or commit SHAs

Version ranges like ^2.1.0 or >= 1.0.0 mean any future compatible version can be pulled into your build. This is convenient for getting updates, but it means a malicious version 2.2.0 would be picked up automatically. For production dependencies, pinning to exact versions and committing a lockfile (package-lock.json, poetry.lock) gives you deterministic builds and a paper trail.

For GitHub Actions specifically, pinning to a full commit SHA rather than a tag is critical:

# Vulnerable — tag can be moved
uses: actions/checkout@v4

# Secure — pinned to exact commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

Software Bill of Materials (SBOM)

An SBOM is a formal, machine-readable inventory of every software component in your application — direct and transitive dependencies, their versions, their origins, and their licenses. Think of it as a nutrition label for software.

Two formats dominate: SPDX (ISO/IEC 5962:2021, maintained by the Linux Foundation) and CycloneDX (OWASP project, supports more security-specific metadata). Both are supported by major tooling.

Generating an SBOM:

# CycloneDX for Node.js
npx @cyclonedx/cyclonedx-npm --output-file sbom.json

# CycloneDX for Python
pip install cyclonedx-bom
cyclonedx-py environment --output-file sbom.json

# Syft (supports 40+ ecosystems)
syft dir:. -o cyclonedx-json > sbom.json

An SBOM on its own is just a list. The value comes from continuously scanning it against vulnerability databases (NVD, OSV, GitHub Advisory Database) and alerting when a component in your inventory gets a new CVE. Tools like Grype, OWASP Dependency-Check, and Dependabot do this automatically.

Prevention and best practices

Use a private package registry with proxying

Host your own npm/PyPI/Maven registry (Artifactory, Nexus, AWS CodeArtifact) and configure it to proxy public registries. This lets you: approve packages before they enter your dependency pool, cache approved versions so you're not dependent on the upstream registry's availability, and block dependency confusion attacks by always preferring your private namespace.

Enable two-factor authentication for package publishers

Most major package registries now support or require 2FA for publishing. The event-stream attack, the ua-parser-js hijack, and dozens of other package takeovers happened because attacker gained access to a maintainer's credentials. NPM made 2FA mandatory for the top 500 most-downloaded packages in 2022. If you maintain public packages, 2FA on your publishing account is non-negotiable.

Implement Supply-chain Levels for Software Artifacts (SLSA)

SLSA (pronounced "salsa") is a security framework from Google that defines four levels of supply chain integrity, from basic version control hygiene (Level 1) to fully audited, hermetic build processes with hardware-rooted provenance (Level 4). Even reaching SLSA Level 2 — which requires automated builds and generating signed provenance — eliminates a large class of build tampering attacks.

Scan before you ship, not just during development

A package that was safe when you first added it might have a CVE published tomorrow. Dependency scanning should run:

Minimal install scripts

If you don't need postinstall scripts, disable them for package installation in CI:

# npm — ignore lifecycle scripts during CI install
npm ci --ignore-scripts

# Only run scripts for packages that explicitly need them
npm install --ignore-scripts
npm rebuild   # rebuilds native addons only

This won't stop a malicious package from running code when your application imports it, but it prevents install-time payloads — a common attack vector used in the ua-parser-js and event-stream incidents.

Verify container image signatures

Use Sigstore/cosign to verify that container images were built by your CI pipeline and haven't been tampered with:

# Sign during build
cosign sign --key cosign.key ghcr.io/yourorg/yourapp:latest

# Verify before deploy
cosign verify --key cosign.pub ghcr.io/yourorg/yourapp:latest

Kubernetes admission controllers like Kyverno or OPA Gatekeeper can enforce signature verification at deploy time, so unsigned images are rejected before they run.

The OWASP A03:2025 connection to A08

There's intentional overlap between A03 (Supply Chain Failures) and A08:2025 (Data Integrity Failures). A08 covers broader data and code integrity failures — insecure deserialization, CI/CD pipelines without integrity checks, auto-update mechanisms without verification. A03 is specifically about the supply chain: third-party packages, build tools, and the ecosystem your code runs on top of.

In practice, fixing both categories involves many of the same controls: signed artifacts, verified builds, lockfiles, and SBOMs. Think of them as two lenses on the same underlying problem.

What scanners can detect

Automated scanning against A03 is inherently limited — you can't dynamically detect that a package was published by a bad actor from a running website. What scanners can detect:

For full supply chain visibility, runtime scanning alone isn't enough. You need SBOM generation in your build pipeline, continuous dependency auditing, and code signing in your CI/CD process.

Check your dependencies

Run a scan to detect outdated libraries, missing SRI hashes, exposed version information, and other supply chain signals in your web application.

Check your dependencies