A Deep Dive Into OWASP Dependency-Check
Modern software heavily relies on open-source libraries and tools. GitHub reports that over 90% of modern applications leverage them to accelerate software development. While this speeds things up, it also introduces potential security risks.
Open-source tools and third-party libraries may contain security vulnerabilities or other malicious code, which can put your system at risk if not properly monitored or updated. For instance, in April 2023, so many spam packages were uploaded to NPM that the repository briefly went offline.
As the saying goes, "You're only as secure as your weakest link." Therefore, it is crucial to ensure your external libraries are up-to-date and secure. This is where the Open Web Application Security Project's (OWASP) Dependency-Check tool comes in.
In this article, we will review OWASP Dependency-Check, how to set it up, and best practices for its use.
What is OWASP Dependency-Check?
OWASP Dependency-Check is an open-source software composition analysis (SCA) tool that detects publicly disclosed vulnerabilities in application dependencies. It was created by the OWASP organization to address one of the OWASP Top 10 vulnerabilities: Vulnerable and outdated components.
Dependency-Check currently provides comprehensive support for Java, Node.js, and .NET-based products, as well as experimental support for Python, Dart, SWIFT, and Golang. It can be executed via the command-line interface (CLI), as an Ant task, or through plugins integrated with Maven, Jenkins, or Gradle.
OWASP Dependency-Check is usually used alongside other security scanning solutions to create a more holistic security strategy.
How Does OWASP Dependency-Check Work?
OWASP Dependency-Check identifies vulnerabilities using analyzers. These analyzers scan your code base for open-source libraries, check for vulnerabilities in them, and generate reports if a vulnerability is found.
Here's how analyzers work under the hood:
- Dependency Analysis: Dependency-Check uses analyzers to examine your project's dependencies. These analyzers collect information (called evidence) about each dependency, like its name and version. For example, in a .NET project using NuGet packages, Dependency-Check would scan the project file to identify dependencies like Newtonsoft.Json version 13.0.3 or EntityFramework.Core version 8.0.0.
- Common Platform Enumeration (CPE): Once the dependencies are identified, Dependency-Check uses the collected information to determine each dependency's Common Platform Enumeration (CPE). The CPE provides a standardized name for software components and versions.
- Vulnerability Matching: Dependency-Check then compares the CPE against the NVD database, which contains each package's Common Vulnerability and Exposure (CVE) entries. For example, if Dependency-Check scans a .NET project and identifies a dependency like Newtonsoft.Json version 13.0.3, it will create a CPE and compare it against the CVE in the NVD. If a match is found, it indicates a known vulnerability for that specific version of Newtonsoft.Json. Dependency-Check will flag this dependency as vulnerable in its report.
- Report Generation: After vulnerability matching, Dependency-Check generates a detailed report highlighting the vulnerable dependencies, specific vulnerabilities, and severity levels. See this example from the Apache Struts 1 project.
It's important to note that the report only lists a dependency once, even if it's vulnerable in multiple locations within your project. So, you'll need to identify all affected areas within your project. Also, the vulnerability scores don't consider your specific application context. It's up to you to evaluate whether the vulnerabilities are relevant to your project's library usage.
5. Additional Data Sources: For specific technologies, Dependency-Check may also use other data sources to identify a wider range of vulnerabilities that might not be listed in the NVD. For example:
- The NPM Audit API is specialized in identifying vulnerabilities in NPM packages for JavaScript projects.
- The OSS Index covers many open-source projects, including those commonly used in .NET development.
- RetireJS is dedicated to detecting outdated JavaScript libraries with known security issues.
- Bundler Audit focuses on vulnerabilities in Ruby Gem dependencies for Ruby on Rails applications.
6. Automatic Updates: Dependency-Check automatically updates its vulnerability data using NVD API to ensure that reports reflect the most recent information.
Setting Up OWASP Dependency-Check in .NET 8.0 (Demo)
This guide demonstrates how to leverage OWASP Dependency-Check in a .NET 8.0 project to identify potential vulnerabilities within your dependencies.
Prerequisites:
- .NET 8.0 SDK: Ensure you have installed the latest .NET 8.0 SDK on your system. You can download it from the official Microsoft website
- OWASP Dependency-Check: Download and install the OWASP Dependency-Check tool
- NVD API key: Get the NVD API key
Creating a Sample .NET 8.0 Application
- Open a terminal or command prompt and create a new directory (dependency-check-demo) for your project.
- For this demo, we will be initializing a new .NET 8.0 console application using the following command:
dotnet new console
3. Next, we add a dependency for our project. We'll use the Newtonsoft.Json library for demonstration purposes. Add it to your project using:
dotnet add package Newtonsoft.Json
4. Open your preferred code editor and navigate to the project directory. In the Program.cs file, replace the existing content with the following code snippet that deserializes a JSON object:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
var json = @"{'name':'John Smith','age':28}";
dynamic obj = JsonConvert.DeserializeObject(json);
Console.WriteLine($"Hello, {obj.name}!");
}
}
5. Build and compile the application using the following command:
dotnet build
6. Run the application using the following command:
dotnet run
If everything functions correctly, you should see the "Hello, John!" message in the console.
Scanning With OWASP Dependency-Check
Now that we have a functional .NET 8.0 application let's leverage Dependency-Check to scan its dependencies for vulnerabilities by running the following command from the command line.
dependency-check --scan . --format HTML --project "dependency-check-demo" --out . --nvdApiKey <your-api-key>
- Dependency-check: Invokes the Dependency-Check tool
- --scan .: Specifies the current directory (".") to be scanned for dependencies
- --format HTML: Defines the output format as HTML for a user-friendly report
- --project "dependency-check-demo": Sets the project name for reference in the report
- --out .: Instructs Dependency-Check to place the generated report in the current directory
Viewing the OWASP Dependency-Check Report
After running the command, you should find a new file named dependency-check-report.html in your project directory. Open this file in a web browser to view the detailed report on identified vulnerabilities within your project's dependencies. In our case, the current version of Newtonsoft.Json does not have any reported vulnerabilities, so it shows as empty.
Best Practices for Using OWASP Dependency-Check
OWASP Dependency-Check is a valuable tool for identifying vulnerabilities within your project's external dependencies. Here are some best practices to maximize its effectiveness:
- Create a Baseline Inventory: The OWASP Dependency-Check is more effective if you have an internal inventory against which to compare. Start by creating a baseline inventory of all the open-source components and third-party libraries used in your software projects. This includes libraries directly used in your codebase and transitive dependencies. A baseline inventory helps prioritize which dependencies require the most attention and track how dependencies evolve.
- Integrate Dependency-Check in CI/CDProcess: Integrate dependency scanning into your CI/CD pipeline to automate scans on every code commit or scheduled build. Tools like Jenkins, GitLab CI/CD, and Azure DevOps often have plugins or scripts that facilitate this integration. Additionally, you can schedule regular manual scans of your project to proactively identify and address potential security risks.
- Stay Up-to-Date: Ensure you're using the latest version of Dependency-Check to benefit from the most recent vulnerability data.
- Consider False Positives and Negatives: While Dependency-Check strives for accuracy, there's a possibility of false positives (identifying a non-existent vulnerability) or false negatives (missing a real vulnerability). A manual review of flagged dependencies is always necessary.
- Review Scan Results: After each build, review the OWASP Dependency-Check report to identify and prioritize vulnerabilities for remediation. Integrate the results with your issue-tracking system to facilitate vulnerability management and tracking.
- Consult Additional Security Measures: Dependency-Check is a valuable tool, but it's not a silver bullet. Use secure coding guidelines and other application security testing methods to improve your overall application's security posture.
Extend Your Dependency-Checks to Full Security Scans
OWASP Dependency-Check is a valuable tool for identifying third-party vulnerabilities in project dependencies — but it's not enough. Complementing Dependency-Check with other automated security testing tools can be highly beneficial in improving the quality of your application security program.
Codacy Security goes beyond Dependency-Check by providing an array of advanced features, including:
- Static Analysis: Detect vulnerabilities and potential security issues in your codebase.
- Third-Party License Compliance Checks: Ensure compliance with all licensing requirements for your open-source projects.
- Auditable Mitigation Workflows: Document and track the entire process of addressing vulnerabilities.
- Real-Time Security Best Practice Recommendations: Offer developers actionable insights and recommendations to enhance your code's overall security.
Get started for free today.