OWASP Web Top 10 — A08

Supply Chain Attacks

Supply Chain Attacks represent one of the most sophisticated and dangerous threats in modern software development. By compromising dependencies, build pipelines, or package registries, attackers can inject malicious code that reaches thousands of organizations at scale, bypassing traditional security controls.

What Are Supply Chain Attacks?

Supply Chain Attacks exploit the trust relationships that exist within the software development and distribution ecosystem. Instead of directly targeting an application, attackers compromise the components, tools, or infrastructure that developers rely on to build and deploy software. This includes open-source dependencies, build tools, CI/CD pipelines, package registries, and third-party services. When a widely-used component is compromised, the malicious code automatically propagates to every application that depends on it.

The attack surface is vast and difficult to defend. Modern applications typically depend on hundreds of third-party packages, each with their own dependencies, creating a complex web of trust. Build pipelines involve multiple stages, tools, and integrations, each representing a potential entry point. Package registries rely on maintainer accounts that can be phished or compromised. Even a single compromised package can affect millions of users, as demonstrated by numerous real-world incidents in recent years.

Supply Chain Attacks have become increasingly prevalent and are now recognized as A08 in the OWASP Top 10 2021 edition under "Software and Data Integrity Failures." Organizations are often blind to these attacks because they occur outside their own infrastructure, making detection and prevention particularly challenging. The transitive nature of dependencies means that a vulnerability several layers deep in the dependency tree can still compromise the final application.

How It Works

1
Attacker identifies a high-value target

The attacker researches popular open-source packages, widely-used build tools, or critical infrastructure components with large downstream impact. They may also target specific organizations by identifying their unique dependencies, build tools, or supply chain vendors through reconnaissance.

2
Compromise occurs at the source

The attacker gains control through various methods: phishing maintainer credentials, exploiting vulnerabilities in package registry accounts, submitting malicious pull requests, typosquatting similar package names, or compromising the build infrastructure itself. In sophisticated attacks, they may compromise developer workstations or CI/CD systems.

3
Malicious code is injected

The attacker injects malicious code into the compromised component. This could be a backdoor in a package update, a malicious dependency added to package.json, a compromised build script that modifies artifacts, or poisoned Docker images. The malicious code is often obfuscated and designed to evade detection during code reviews.

4
Automated distribution spreads the compromise

The compromised component is distributed through normal channels: npm publish, Maven Central uploads, Docker Hub pushes, or CI/CD pipeline artifacts. Developers unknowingly download and integrate the malicious version through automated dependency updates, build processes, or manual installations. The trust in the source makes the malicious code seem legitimate.

5
Payload executes at scale

The malicious code executes in countless production environments, often with the same privileges as the legitimate application. This can result in data exfiltration, credential theft, backdoor installation, or lateral movement within networks. Because the attack originates from a trusted source, it often bypasses security controls like firewalls and application whitelisting.

Vulnerable Code Example

Vulnerable — Java / Spring Boot
<!-- pom.xml -->
<dependencies>
    <!-- VULNERABLE: No version pinning, no checksum verification -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- Using LATEST or RELEASE versions -->
        <version>LATEST</version>
    </dependency>

    <dependency>
        <groupId>com.third-party</groupId>
        <artifactId>util-library</artifactId>
        <!-- Floating version ranges allow automatic updates -->
        <version>[1.0,2.0)</version>
    </dependency>
</dependencies>

<!-- .github/workflows/build.yml -->
name: Build and Deploy

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # VULNERABLE: Using third-party actions without hash pinning
      - uses: actions/checkout@v3

      # VULNERABLE: Unverified third-party action
      - uses: some-org/build-action@main

      # VULNERABLE: No artifact signing or integrity checks
      - name: Build
        run: mvn clean package

      # VULNERABLE: Secrets exposed to all steps
      - name: Deploy
        env:
          AWS_ACCESS_KEY: ${{ secrets.AWS_KEY }}
        run: ./deploy.sh

# RISKS:
# - Any compromised dependency auto-updates into production
# - Third-party GitHub Actions can access secrets
# - No verification of artifact integrity
# - Build pipeline has excessive permissions

Secure Code Example

Secure — Java / Spring Boot (Hardened Pipeline)
<!-- pom.xml -->
<dependencies>
    <!-- SECURE: Pinned versions with checksums -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.1.5</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- SECURE: Generate and verify SBOM (Software Bill of Materials) -->
        <plugin>
            <groupId>org.cyclonedx</groupId>
            <artifactId>cyclonedx-maven-plugin</artifactId>
            <version>2.7.9</version>
        </plugin>

        <!-- SECURE: Sign artifacts -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <version>3.1.0</version>
        </plugin>
    </plugins>
</build>

<!-- .github/workflows/build.yml -->
name: Secure Build and Deploy

on: [push]

permissions:
  contents: read
  id-token: write  # For OIDC authentication

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # SECURE: Hash-pinned actions for immutability
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

      - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
        with:
          java-version: '17'

      # SECURE: Verify dependencies against known vulnerabilities
      - name: Dependency Check
        run: mvn dependency-check:check

      # SECURE: Generate SBOM for supply chain transparency
      - name: Generate SBOM
        run: mvn cyclonedx:makeAggregateBom

      # SECURE: Sign build artifacts
      - name: Build and Sign
        run: |
          mvn clean package
          mvn gpg:sign-and-deploy-file

      # SECURE: Secrets scoped to specific step only
      - name: Deploy
        uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502
        with:
          role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE }}
          aws-region: us-east-1

# PROTECTIONS:
# - Pinned dependency versions prevent automatic malicious updates
# - Hash-pinned GitHub Actions ensure immutability
# - SBOM provides full supply chain visibility
# - Signed artifacts enable integrity verification
# - Minimal permissions and OIDC reduce credential theft risk

Types of Supply Chain Attacks

Compromised Dependencies

Attackers inject malicious code into popular open-source packages by compromising maintainer accounts, submitting malicious pull requests, or using typosquatting (creating packages with names similar to popular ones). The event-stream incident in 2018 demonstrated this when a legitimate npm package was transferred to an attacker who added cryptocurrency-stealing code. Dependency confusion attacks exploit how package managers resolve private vs. public packages, tricking systems into installing malicious public packages instead of internal ones.

Build Pipeline Attacks

Attackers compromise CI/CD systems, build servers, or developer workstations to inject malicious code during the build process. The SolarWinds attack used this technique, where attackers gained access to the build environment and inserted a backdoor during the compilation process. GitHub Actions and third-party CI/CD plugins represent attack vectors when used without proper verification. Codecov's compromise in 2021 showed how build tool credentials can be stolen to access customer environments. Build-time attacks are particularly dangerous because the source code may be clean while the compiled artifacts are compromised.

Registry & Distribution Attacks

Attackers compromise package registries, update servers, or content delivery networks to distribute malicious software. Namespace hijacking exploits abandoned or expired package names to publish malicious versions. The ua-parser-js compromise on npm showed how attackers can gain control of legitimate packages and push malicious updates that auto-install on millions of machines. Docker image poisoning involves uploading malicious container images with popular names. CDN compromises can serve malicious JavaScript to countless websites, as demonstrated by attacks on Polyfill.io and other CDN providers.

Impact

Supply Chain Attacks have catastrophic potential because they exploit trust relationships and distribute malicious code at massive scale. A single compromised component can affect thousands of organizations simultaneously.

Widespread backdoor installation

Attackers gain persistent access to countless systems simultaneously. The SolarWinds attack compromised approximately 18,000 organizations, including government agencies and Fortune 500 companies. Backdoors can remain undetected for months or years, providing attackers with ongoing access to sensitive systems, networks, and data.

Credential and secret theft

Malicious dependencies can access environment variables, configuration files, and credential stores during build or runtime. The Codecov compromise allowed attackers to steal secrets from CI/CD environments, potentially affecting hundreds of companies. Stolen credentials enable lateral movement and can be used to compromise additional systems beyond the initial target.

Data exfiltration at scale

Compromised packages can exfiltrate sensitive data from every application that uses them. This includes customer data, intellectual property, source code, and business secrets. The trust placed in dependencies means malicious code often runs with full application privileges, accessing databases, APIs, and file systems without restriction.

Regulatory and reputational damage

Organizations affected by supply chain attacks face massive regulatory fines under GDPR, CCPA, and other frameworks. Customer trust is severely damaged when compromises are publicized. The cost of incident response, forensics, notification, and remediation can reach hundreds of millions of dollars. Legal liability extends to downstream customers affected by the compromise.

Prevention Checklist

Pin dependency versions with checksums

Always use exact version pinning in dependency files (package.json, pom.xml, requirements.txt). Never use floating versions like LATEST, *, or version ranges. Use lock files (package-lock.json, yarn.lock, Pipfile.lock) to ensure deterministic builds. Verify checksums/hashes of downloaded dependencies to detect tampering. Consider using private dependency mirrors to control what enters your environment.

Implement Software Bill of Materials (SBOM)

Generate and maintain SBOMs in formats like CycloneDX or SPDX for all applications. SBOMs provide complete visibility into your dependency tree, including transitive dependencies. Automate SBOM generation in your CI/CD pipeline. Use SBOMs to quickly identify affected systems when vulnerabilities are disclosed. Share SBOMs with customers for supply chain transparency.

Secure your CI/CD pipeline

Pin GitHub Actions and other CI/CD plugins to specific commit hashes, not tags or branches. Use minimal permissions for CI/CD jobs following the principle of least privilege. Implement OIDC authentication instead of long-lived credentials. Isolate build environments and use ephemeral build agents. Enable audit logging for all pipeline activities. Require signed commits and enforce branch protection rules.

Scan dependencies for vulnerabilities

Integrate dependency scanning tools like Snyk, Dependabot, or OWASP Dependency-Check into your CI/CD pipeline. Configure automated alerts for new vulnerabilities in your dependencies. Establish a process for rapid patching when vulnerabilities are discovered. Monitor security advisories for packages you depend on. Regularly audit and remove unused dependencies to reduce attack surface.

Sign and verify artifacts

Cryptographically sign all build artifacts, container images, and release packages using tools like GPG, Sigstore, or Docker Content Trust. Verify signatures before deployment to ensure artifacts haven't been tampered with. Implement artifact provenance to create a verifiable chain of custody from source to deployment. Use admission controllers in Kubernetes to enforce signature verification.

Vet dependencies before adoption

Evaluate packages before adding them to your project: check maintainer reputation, project activity, number of contributors, and community trust. Prefer packages with security audits and active maintenance. Review the dependency's own dependencies for red flags. Be cautious of packages with few downloads or recently published packages claiming to be popular libraries (potential typosquatting). Consider the blast radius of adding a new dependency.

Real-World Examples

2020

SolarWinds Sunburst

One of the most sophisticated supply chain attacks in history. Nation-state actors compromised SolarWinds' build system and injected the SUNBURST backdoor into Orion software updates. Approximately 18,000 organizations installed the compromised updates, including U.S. government agencies, technology companies, and critical infrastructure providers. The attack remained undetected for months, demonstrating the stealth and impact of supply chain compromises.

2021

Codecov Bash Uploader

Attackers compromised Codecov's Bash Uploader script, which is executed in CI/CD pipelines to upload code coverage reports. The modified script extracted sensitive environment variables, including credentials and tokens, and sent them to an attacker-controlled server. Hundreds of companies using Codecov in their CI/CD pipelines were potentially affected, leading to widespread credential rotation and security reviews across the industry.

2021

ua-parser-js npm Compromise

The ua-parser-js npm package, which receives millions of weekly downloads, was compromised when attackers gained access to the maintainer's npm account. Three malicious versions were published containing cryptocurrency miners and password-stealing malware. The package is used by major companies worldwide, and the compromise affected countless applications before the malicious versions were identified and removed.

2023

3CX Desktop App

A supply chain attack compromised 3CX's Desktop App installer, affecting over 600,000 companies worldwide. Attackers trojanized the application's installer, distributing malware through official update channels. The attack was traced back to a compromised employee workstation and highlighted how attackers can infiltrate software build processes. The incident affected organizations globally and required mass uninstallation and security reviews.

Ready to Test Your Knowledge?

Put what you have learned into practice. Try identifying and preventing supply chain vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.