A Comprehensive Guide to OWASP Dependency-Check in Java

In modern software development, applications are built using numerous third-party dependencies, making supply chain security a critical concern. OWASP Dependency-Check is an open-source tool that scans your project dependencies for known vulnerabilities, helping you identify and remediate security risks before they reach production. This guide explores how to effectively integrate and use Dependency-Check in Java projects.


What is OWASP Dependency-Check?

Dependency-Check is a Software Composition Analysis (SCA) tool that identifies project dependencies and checks against known vulnerability databases. It works by creating a fingerprint of each dependency and comparing it against the National Vulnerability Database (NVD) and other sources.

Key Features:

  • Multi-language Support: Java, .NET, JavaScript, Python, Ruby, PHP, and more
  • Multiple Database Support: NVD, Retire.js, NPM Advisory, etc.
  • Build Tool Integration: Maven, Gradle, Ant, SBT
  • CI/CD Friendly: Command-line interface and plugins
  • Evidence-Based Analysis: Uses filename, hashes, and package information

How Dependency-Check Works

Dependency-Check Workflow:
1. Scan Dependencies → 2. Collect Evidence → 3. Generate Fingerprint → 4. Check Databases → 5. Generate Report

Analysis Process:

  1. Dependency Collection: Identifies all dependencies in your project
  2. Evidence Gathering: Collects information from filenames, hashes, and package metadata
  3. Fingerprinting: Creates unique identifiers for each dependency
  4. Vulnerability Matching: Compares fingerprints against vulnerability databases
  5. Reporting: Generates detailed reports with vulnerability information

Installation and Setup

1. System Requirements

  • Java 8 or higher
  • 4GB+ RAM (for large projects)
  • Internet access (for database updates)

2. Download Standalone CLI

# Download latest version
wget https://github.com/jeremylong/DependencyCheck/releases/download/v9.0.7/dependency-check-9.0.7-release.zip
unzip dependency-check-9.0.7-release.zip
cd dependency-check/bin

3. Verify Installation

./dependency-check.sh --version
# or on Windows
dependency-check.bat --version

Maven Integration

1. Basic Maven Plugin Configuration

<project>
<build>
<plugins>
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.0.7</version>
<configuration>
<format>HTML</format>
<failBuildOnAnyVulnerability>true</failBuildOnAnyVulnerability>
<failOnCVSS>7</failOnCVSS>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

2. Advanced Maven Configuration

<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.0.7</version>
<configuration>
<!-- Report Formats -->
<formats>HTML,JSON,XML</formats>
<!-- Failure Configuration -->
<failBuildOnAnyVulnerability>true</failBuildOnAnyVulnerability>
<failOnCVSS>8</failOnCVSS>
<!-- Scan Configuration -->
<scanSet>
<scan>
<fileSet>
<directory>${project.basedir}</directory>
<includes>
<include>**/*.jar</include>
<include>**/package-lock.json</include>
</includes>
</fileSet>
</scan>
</scanSet>
<!-- Suppression File -->
<suppressionFiles>
<suppressionFile>dependency-check-suppressions.xml</suppressionFile>
</suppressionFiles>
<!-- Database Configuration -->
<cveValidForHours>24</cveValidForHours>
<nvdApiKey>${nvd.api.key}</nvdApiKey>
<!-- Performance Tuning -->
<jarAnalyzerEnabled>true</jarAnalyzerEnabled>
<nodeAnalyzerEnabled>true</nodeAnalyzerEnabled>
<nodeAuditAnalyzerEnabled>true</nodeAuditAnalyzerEnabled>
<retireJsAnalyzerEnabled>true</retireJsAnalyzerEnabled>
</configuration>
</plugin>

3. Running with Maven

# Basic scan
mvn dependency-check:check
# Skip tests for faster scanning
mvn dependency-check:check -DskipTests
# Update local database first
mvn dependency-check:update-only
mvn dependency-check:check
# With custom properties
mvn dependency-check:check -DfailBuildOnAnyVulnerability=false

Gradle Integration

1. Basic Gradle Plugin Setup

// build.gradle.kts
plugins {
id("org.owasp.dependencycheck") version "9.0.7"
}
dependencyCheck {
format = listOf("HTML", "JSON", "XML")
failBuildOnCVSS = 8.0f
analyzers.assemblyEnabled = false
}
tasks.named("dependencyCheckAnalyze") {
dependsOn("assemble")
}

2. Advanced Gradle Configuration

dependencyCheck {
// Output Configuration
formats = listOf("HTML", "JSON", "XML")
outputDirectory = file("${buildDir}/reports/dependency-check")
// Failure Configuration
failBuildOnAnyVulnerability = true
failOnCVSS = 7.0f
// Scan Configuration
scanConfigurations = listOf("runtimeClasspath")
scanSet = files(
fileTree("src/main/resources") {
include("**/*.jar")
}
)
// Suppression File
suppressionFile = "dependency-check-suppressions.xml"
// Database Configuration
cveValidForHours = 12
nvd.api.key = project.properties["nvdApiKey"] as? String
// Analyzer Configuration
analyzers {
assemblyEnabled = false
jarAnalyzerEnabled = true
nodeEnabled = true
nodeAuditEnabled = true
retireJsEnabled = true
swiftEnabled = false
cocoapodsEnabled = false
}
// Data Mirror Configuration
data {
directory = "${project.rootDir}/dependency-check-data"
}
}

3. Running with Gradle

# Basic scan
./gradlew dependencyCheckAnalyze
# Update database
./gradlew dependencyCheckUpdate
# Generate aggregate report for multi-project
./gradlew dependencyCheckAggregate

Standalone CLI Usage

1. Basic CLI Scan

# Scan a Java project
./dependency-check.sh --project "My Application" --scan "target/*.jar" --out reports/
# Scan with multiple paths
./dependency-check.sh \
--project "My Microservice" \
--scan "service-a/target/*.jar" \
--scan "service-b/target/*.jar" \
--scan "frontend/package-lock.json" \
--format HTML \
--format JSON \
--out ./security-reports

2. Advanced CLI Configuration

./dependency-check.sh \
--project "Enterprise Application" \
--scan "/path/to/application" \
--suppression "dependency-check-suppressions.xml" \
--enableRetired \
--failOnCVSS 8 \
--nvdApiKey $NVD_API_KEY \
--cveValidForHours 6 \
--data "/opt/dependency-check/data" \
--connectionTimeout 60000 \
--proxyserver proxy.company.com \
--proxyport 8080 \
--hints hints.xml

Suppression Files and False Positives

1. Creating Suppression File

<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<!-- Suppress by CVE -->
<suppress>
<notes><![CDATA[
False positive - this vulnerability doesn't affect our usage
]]></notes>
<cve>CVE-2023-12345</cve>
</suppress>
<!-- Suppress by Dependency -->
<suppress>
<notes><![CDATA[
We've validated this dependency is safe in our context
]]></notes>
<gav>com.example:library:1.2.3</gav>
<cve>CVE-2023-67890</cve>
</suppress>
<!-- Suppress All Vulnerabilities for a Dependency -->
<suppress base="true">
<notes><![CDATA[
Internal library with no external dependencies
]]></notes>
<gav>com.company:internal-utils:2.0.0</gav>
</suppress>
<!-- Suppress by File Hash -->
<suppress>
<notes><![CDATA[
Custom patched version of the library
]]></notes>
<sha1>a1b2c3d4e5f6789012345678901234567890123</sha1>
</suppress>
<!-- Suppress Until Date -->
<suppress until="2024-12-31">
<notes><![CDATA[
Waiting for patch to be available
]]></notes>
<gav>org.springframework:spring-core:5.3.8</gav>
<cve>CVE-2023-98765</cve>
</suppress>
<!-- Suppress by Vulnerability Type -->
<suppress>
<notes><![CDATA[
This is a build-time only dependency
]]></notes>
<gav>org.apache.maven.plugins:maven-compiler-plugin:3.11.0</gav>
<vulnerabilityName>.*denial of service.*</vulnerabilityName>
</suppress>
</suppressions>

2. Auto-generate Suppression Template

# Generate suppression template from existing report
./dependency-check.sh \
--project "Generate Suppressions" \
--scan "target/dependency" \
--format "JSON" \
--out "reports"
# Then convert findings to suppression format

CI/CD Integration

1. GitHub Actions Workflow

name: Dependency Security Scan
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * 1'  # Weekly on Monday at 2 AM
jobs:
dependency-check:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Dependency-Check data
uses: actions/cache@v3
with:
path: ~/.dependency-check/data
key: ${{ runner.os }}-dependency-check-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-dependency-check-
- name: Run Dependency-Check
run: |
mvn org.owasp:dependency-check-maven:check
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
- name: Upload Dependency-Check report
uses: actions/upload-artifact@v3
with:
name: dependency-check-report
path: target/dependency-check-report.html
retention-days: 30
- name: Check for critical vulnerabilities
run: |
if grep -q "CRITICAL" target/dependency-check-report.html; then
echo "Critical vulnerabilities found!"
exit 1
fi

2. Jenkins Pipeline

pipeline {
agent any
tools {
maven 'Maven_3.8'
}
stages {
stage('Dependency Check') {
steps {
script {
// Update vulnerability database
sh 'mvn org.owasp:dependency-check-maven:update-only'
// Run dependency check
sh 'mvn org.owasp:dependency-check-maven:check -DfailBuildOnCVSS=8'
}
}
post {
always {
dependencyCheckPublisher(
pattern: '**/dependency-check-report.xml',
failedTotalHigh: '10',
failedTotalCritical: '1',
unstableTotalHigh: '5',
unstableTotalCritical: '0'
)
archiveArtifacts artifacts: '**/dependency-check-report.*', fingerprint: true
}
}
}
}
}

Advanced Configuration and Customization

1. Custom Analyzers Configuration

<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.0.7</version>
<configuration>
<analyzers>
<!-- Enable/disable specific analyzers -->
<jarAnalyzerEnabled>true</jarAnalyzerEnabled>
<nodeAnalyzerEnabled>true</nodeAnalyzerEnabled>
<nodeAuditAnalyzerEnabled>true</nodeAuditAnalyzerEnabled>
<retireJsAnalyzerEnabled>true</retireJsAnalyzerEnabled>
<composerAnalyzerEnabled>false</composerAnalyzerEnabled>
<pythonAnalyzerEnabled>false</pythonAnalyzerEnabled>
<rubyAnalyzerEnabled>false</rubyAnalyzerEnabled>
<cocoaPodsAnalyzerEnabled>false</cocoaPodsAnalyzerEnabled>
<swiftAnalyzerEnabled>false</swiftAnalyzerEnabled>
<archiveAnalyzerEnabled>true</archiveAnalyzerEnabled>
<assemblyAnalyzerEnabled>true</assemblyAnalyzerEnabled>
<nugetconfAnalyzerEnabled>false</nugetconfAnalyzerEnabled>
<nuspecAnalyzerEnabled>false</nuspecAnalyzerEnabled>
<centralAnalyzerEnabled>true</centralAnalyzerEnabled>
<nexusAnalyzerEnabled>false</nexusAnalyzerEnabled>
<openSSLAnalyzerEnabled>true</openSSLAnalyzerEnabled>
</analyzers>
</configuration>
</plugin>

2. Database Configuration

<configuration>
<connectionString>jdbc:h2:file:~/.dependency-check/data/dc;AUTOCOMMIT=ON</connectionString>
<dataDirectory>${user.home}/.dependency-check/data</dataDirectory>
<cveUrlModified>https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-modified.json.gz</cveUrlModified>
<cveUrlBase>https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-%d.json.gz</cveUrlBase>
<cveStartYear>2002</cveStartYear>
<cveValidForHours>12</cveValidForHours>
</configuration>

3. Proxy Configuration

<configuration>
<proxyserver>proxy.company.com</proxyserver>
<proxyport>8080</proxyport>
<proxyusername>proxyuser</proxyusername>
<proxypassword>proxypass</proxypassword>
<nonProxyHosts>localhost|*.internal.company.com</nonProxyHosts>
<connectionTimeout>60000</connectionTimeout>
</configuration>

Integrating with Security Tools

1. SonarQube Integration

<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</plugin>
<!-- Run dependency check before SonarQube -->
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>9.0.7</version>
<executions>
<execution>
<id>dependency-check</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>

2. Generating SARIF Reports for GitHub

<configuration>
<formats>HTML,SARIF</formats>
</configuration>

Custom Java Application Integration

1. Programmatic Usage

public class DependencyCheckRunner {
public void runDependencyCheck(File projectDir, File outputDir) throws Exception {
Engine engine = new Engine();
// Configure settings
Settings settings = engine.getSettings();
settings.setString(Settings.KEYS.AUTO_UPDATE, "true");
settings.setString(Settings.KEYS.SUPPRESSION_FILE, 
"dependency-check-suppressions.xml");
settings.setString(Settings.KEYS.ANALYZER_NEXUS_ENABLED, "false");
// Configure database connection
settings.setString(Settings.KEYS.DB_CONNECTION_STRING,
"jdbc:h2:file:" + outputDir.getAbsolutePath() + "/odc;AUTOCOMMIT=ON");
try {
// Scan dependencies
engine.scan(projectDir);
// Analyze dependencies
engine.analyzeDependencies();
// Write reports
ReportGenerator reportGenerator = new ReportGenerator(
"My Application", engine.getDependencies(), engine.getSettings()
);
reportGenerator.generateReports(
outputDir.getAbsolutePath(),
new ReportGenerator.Format[] { 
ReportGenerator.Format.HTML, 
ReportGenerator.Format.JSON 
},
"Dependency Check Report"
);
} finally {
engine.close();
}
}
}

2. Spring Boot Integration

@Component
public class DependencyCheckService {
private static final Logger logger = LoggerFactory.getLogger(DependencyCheckService.class);
@EventListener(ApplicationReadyEvent.class)
public void runSecurityScan() {
if (isSecurityScanEnabled()) {
logger.info("Starting dependency security scan...");
try {
runDependencyCheck();
logger.info("Dependency security scan completed");
} catch (Exception e) {
logger.error("Dependency security scan failed", e);
}
}
}
private void runDependencyCheck() throws Exception {
// Implementation using programmatic API
}
@Bean
@Profile("!prod")
public DependencyCheckRunner dependencyCheckRunner() {
return new DependencyCheckRunner();
}
}

Best Practices

1. Scan Frequency

  • Pre-commit: Quick scans during development
  • CI Pipeline: Full scans on pull requests
  • Scheduled: Daily or weekly comprehensive scans
  • Release Gates: Mandatory scans before production deployment

2. Vulnerability Management

public class VulnerabilityManagementService {
public VulnerabilityAssessment assessVulnerabilities(File dependencyCheckReport) {
List<Vulnerability> vulnerabilities = parseReport(dependencyCheckReport);
return vulnerabilities.stream()
.filter(this::isRelevant)
.filter(vuln -> vuln.getCvssScore() >= 7.0)
.collect(Collectors.toList());
}
private boolean isRelevant(Vulnerability vulnerability) {
// Filter out false positives and irrelevant vulnerabilities
return !vulnerability.isFalsePositive() &&
vulnerability.isExploitable() &&
!isBuildTimeOnly(vulnerability);
}
}

3. Risk Assessment Matrix

public enum RiskLevel {
CRITICAL(9.0, 10.0, "Immediate action required"),
HIGH(7.0, 8.9, "Address within 1 week"),
MEDIUM(4.0, 6.9, "Address within 1 month"),
LOW(0.1, 3.9, "Monitor and plan"),
NONE(0.0, 0.0, "No action required");
private final double minScore;
private final double maxScore;
private final String action;
// Constructor, getters...
public static RiskLevel fromCVSS(double cvssScore) {
for (RiskLevel level : values()) {
if (cvssScore >= level.minScore && cvssScore <= level.maxScore) {
return level;
}
}
return NONE;
}
}

Troubleshooting Common Issues

1. Performance Optimization

<configuration>
<!-- Limit memory usage -->
<jvmFlags>
<jvmFlag>-Xmx4g</jvmFlag>
<jvmFlag>-Xms1g</jvmFlag>
</jvmFlags>
<!-- Disable unused analyzers -->
<analyzers>
<pythonAnalyzerEnabled>false</pythonAnalyzerEnabled>
<rubyAnalyzerEnabled>false</rubyAnalyzerEnabled>
</analyzers>
</configuration>

2. Database Update Issues

# Manual database update
./dependency-check.sh --updateonly --connectionTimeout 120000
# Use offline mode if updates fail
./dependency-check.sh --project "MyApp" --scan "target" --noupdate

3. Memory Issues with Large Projects

# Increase heap size
export JAVA_OPTS="-Xmx8g -Xms2g"
./dependency-check.sh --project "LargeApp" --scan "."

Conclusion

OWASP Dependency-Check provides Java developers with a powerful tool for securing software supply chains by:

  1. Comprehensive Scanning: Detects vulnerabilities across multiple ecosystems
  2. Continuous Monitoring: Integrates seamlessly into CI/CD pipelines
  3. Actionable Reports: Provides detailed information for remediation
  4. Flexible Configuration: Adapts to various project requirements
  5. Enterprise Ready: Scales from small projects to large microservices architectures

By integrating Dependency-Check into your development workflow, you can proactively identify and address security vulnerabilities, reduce attack surfaces, and maintain the integrity of your software supply chain. The key to success is establishing a consistent scanning regimen, properly configuring suppression files for false positives, and integrating security scanning into your development culture.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper