OWASP Dependency Check for Vulnerability Reporting

Recent major data losses and security vulnerabilities in open source frameworks (and the applications that use them) have caused the companies that use those frameworks to have elevated concerns regarding vulnerabilities. The elevated awareness is for good reason, too. After all, no one wants to be the next one to lose sensitive data, be the punching bag of others, or be the example of what not to do security-wise.

Dealing with application vulnerabilities is not only a developer concern but a concern at all levels of organizations. Companies cannot fool others by blaming only the developers when bad things do happen.

If you happen to be in a group that doesn’t have any open source vulnerability reporting, OWASP Dependency-Check may be your short-term answer to get at least something in place. Adding OWASP Dependency-Check into your build process takes a relatively low effort. Other than not having the technology that stack Dependency-Check can help you with, there isn’t a reason not to at least add Dependency-Check to give a little insight into your open source dependencies.

The following parts will help you get Dependency-Check integrated into your Java project’s build process. The instructions will be adaptable to the other technologies Dependency-Check supports, like Gradle or JavaScript. Dependency-Check is also available as a command line tool for your favorite OS.

Our Example

In this example, I’ll use a Java project with Maven. I don’t have any code in the project since Dependency-Check only cares about dependences and not source code under /src/main or /src’test. The important parts are what exists in the POM.XML and /lib.

For a quick description, Dependency-Check uses a variety of analyzers to build a list of Common Platform Enumeration (CPE) entries. The JAR and Archive analyzers are the two analyzers most commonly used for Java projects. The JAR analyzer analyzes each GAV in the POM.XML file and builds the CPE for the dependency. The analyzer can also inspect JARs managed outside of Maven by utilizing the archive manifest metadata. The Archive analyzer targets other archive formats such as the ZIP archive format and then uses the other analyzers for the archive contents.

The Archive analyzer seems to catch archive files in most project locations, but I haven’t tried them all. The analyzer is a little funky when a JAR (same CPE) that contains a vulnerability was found in several locations or archives. The JAR is reported once, even though it can reside in several locations within the project.

Dependency-Check uses the CPE as the lookup identifier in its database of associated Common Vulnerability and Exposure (CVE) entries. We’ll go over the drawbacks of the CPE method later. When using Dependency-Check with Maven, Dependency-Check downloads the NIST NVD Data Feeds to the default configuration location which is in the local Maven M2 repository (org/owasp/…./data). The location is the same for the local environment and Jenkins.

Extra Information

When the Dependency-Check Maven plugin executes, Dependency-Check downloads the NVD Data Feed if done for the first time or has been longer than the default four hours. The initial download can take 10 – 20+ minutes. The data is stored in an H2 database located in the local M2 repo. Once the vulnerability data has been downloaded, Dependency-Check uses the CPE to retrieve the CVE information from the H2 database. The report is then generated with this information and add to the default /target directory.

Each plugin configuration is attached to a Maven lifecycle phase by default. The build plugin configuration is attached to the verify phase and the report plugin configuration is attached to the site phase.

If you don’t want the build plugin to be attached to a Maven phase then remove the execution block. To run without the execution block, add dependency-check:check as a Maven goal.

I used ALL as the format value so XML, CSV, JSON, and HTML based reports will be generated. If you’re not publishing the findings to other products like SonarQube, then HTML will work.

Aggregate goal

If you have a Maven multi-module project, Dependency-Check provides an aggregate goal along with the check goal. This will allow the child project results to get rolled-up into the parent project report. Some of the details of the child project in which the CVE exists is lost as a result.

Generated Vulnerability Reports

Application Vulnerability Summary:

List of vulnerabilities by CVE:

Make Everyone Responsible

Unless you already have the site phase publishing the reports to a highly visible location, the default /target report location isn’t going to cut it if you want the proper eyeballs viewing the vulnerabilities. The whole idea is to get the vulnerabilities in front of the proper eyeballs so the vulnerabilities can get remediated.

Publishing the (XML and HTML) results to a good code quality platform like SonarQube will really help. The SonarQube Dependency-Check plugin is still fairly static, but it has the effect and it is improving.

Get the report in front of developers, IT leaders, and business leaders. Use the CVE information to help create an understanding of the risk associated by now remediating the vulnerability. Make it everyone’s responsibility to have zero vulnerabilities. Make it a quality control gate as part of the build process.

CVE Example:

Configuring Dependency-Check to fail the build when a vulnerability is identified (failBuildOnAnyVulnerability, failBuildOnCVSS) is a valid option.

Advanced Setup

Extra Setup For Performance

There are a few configuration defaults that can be overridden to make sure each build job isn’t slowed down too much by the Dependency-Check plugin. The analyzers are fairly quick but there could be a penalty if a data update is performed. As mentioned before, the initial database download is a drag but each incremental update is minor assuming Dependency-Check run a few times a day.

The reduce the time and distance it takes to reach the data, the NVD database can be mirrored on an internal server. The internal pipeline to the data will be better equipped to handle the requests rather than the pipeline to nvd.nist.gov.

Dependency-Check also provides an update-only goal that updates the local cache.

We ended up not doing these overrides since jobs always run frequently and data updates are quick enough when accessing external URLs.

Extra Setup for Better Enterprise Environments

Switch the database!

The default database location is /org/owasp/dependency-check-data/3.0/dc.h2.db.

With each Dependency-Check access to the default H2 database, a lock is made on the database. This lock will block other reads from being executed. This isn’t good for your continuous integration environment.

CPE Drawbacks

“Dependency-check does not currently use file hashes for identification. If the dependency was built from source the hash likely will not match the “published” hash. While the evidence-based mechanism currently used can also be unreliable the design decision was to avoid maintaining a hash database of known vulnerable libraries. A future enhancement may add some hash matching for very common well-known libraries (Spring, Struts, etc.).”
– https://jeremylong.github.io/DependencyCheck/general/internals.html

In other words, you may need to utilize the suppression and hint files due to the higher rate of false positives and false negatives. The dependency identification errors are minimal if the dependency is listed in a Maven POM file.

Configuration nexusAnalyzerEnabled and centralAnalyzerEnabled Options

Be careful with the default behavior of these options. The Nexus Analyzer require Sonatype Nexus Pro. If the nexusAnalyzerEnabled or centralAnalyzerEnabled options were set to true without a backend service present, a service not found exception is thrown. The exception handling behavior changes across plugin versions. Older versions of the plugin hide the exception and newer versions ones would fail the build. It appears the very latest (v3.2.1) will automatically disable the analyzer if the Nexus service cannot be reached.

Why Paid Solutions Are Worth It

If you really want to stay ahead of the vulnerability curve, paying for a solution is the way to go. Granted, the solutions are not cheap, but neither is the penalty if data gets leaked due to a vulnerability.

Dependency-Check reports on vulnerabilities that have made it into the NVD database. While this is a legit database of vulnerabilities, the downside is the length of time it takes for vulnerabilities to be proven and through the verification process. This means a vulnerability could be in the wild for a while.

Paid solutions (Snyk, Black Duck, AquaSec, JFrog, Sonatype, ..) offer teams that are proactively researching potential issues in various sources that allow their databases be way ahead of what the NVD database can offer. They also offer other important dependency data points like licensing, popularity, and age.

The Wrap Up

OWASP Dependency-Check provides a solution to get a basic dependency vulnerability analyzer in place for every development shop. Use the reports Dependency-Check generates to get the list of vulnerabilities and their known risks in front of everyone’s eyes so it forces the issue of remediation.

A dependency vulnerability analyzer should be mandatory in every build process. You owe it to your users.