A security vulnerability in Axios 1.1.4 brought to my attention the issue of Ai installing itself on my sandbox, or what other people installs without my knowledge. Because the vulnerability in Axios is so serious, I had to do something. I don’t work with npm, in fact, I rarely do anything with it, but my coworkers do, and I have to trust that they’re maintaining dependencies. But trusting and verifying are two different things …
Jenkins OWASP Dependency-Check Integration
OWASP Dependency-Check is a Software Composition Analysis (SCA) tool that scans your project’s dependencies and identifies known publicly disclosed vulnerabilities. It works by analyzing JAR files,
pom.xml,package.json, and other dependency manifests to extract library names and versions, then matches them against the NVD (National Vulnerability Database) maintained by NIST.Each vulnerability is identified by a CVE identifier and scored on the CVSS scale from 0 to 10 — where 9.0+ is Critical. The tool generates detailed reports in multiple formats (HTML, JSON, XML, SARIF) showing which library is vulnerable, what the CVE describes, and whether a fix (newer version) is available.
It maintains a local H2 database cache of the NVD data. The first download takes 15–30 minutes (~238k records), but subsequent runs only fetch a small diff, making them fast. An NVD API key is strongly recommended — without it requests are heavily throttled.
The tool supports Java, .NET, Python, Ruby, and Node.js. For Java/Gradle it scans
runtimeClasspathdependencies. It also integrates with Sonatype OSS Index and RetireJS for broader coverage, though both now require separate API tokens.False positives do occur — the CPE matching algorithm sometimes maps a library to the wrong CVE. The tool supports a
suppressions.xmlfile where you can document and exclude confirmed false positives from reports.The Jenkins plugin acts as a publisher — it reads the XML report generated by the Gradle/Maven task and renders it inside Jenkins UI as a trend chart and findings list. It does not run the scan itself; the scan is handled by the Gradle plugin during the build step.
Goal: Integrate OWASP Dependency-Check into an existing Jenkins pipeline running inside a Docker container.
// build.gradle
plugins {
id 'org.owasp.dependencycheck' version '12.1.0' // 9.0.9 had API key bugs
}
dependencyCheck {
data {
// Persisted via Docker volume – survives container restarts
directory = '/var/jenkins_home/dependency-check-data'
}
nvd {
apiKey = System.getenv("NVD_API_KEY")
delay = 30000
maxRetryCount = 5
}
analyzers {
ossIndex { enabled = false } // requires token since Sept 2025
nodeAudit { enabled = false } // breaks on package.json aliases
}
format = 'ALL'
outputDirectory = 'build/reports/dependency-check'
scanConfigurations = ['runtimeClasspath']
}stage('Security Scan') {
steps {
withCredentials([string(credentialsId: 'nvd-api-key', variable: 'NVD_API_KEY')]) {
withEnv(["NVD_API_KEY=${NVD_API_KEY}"]) {
sh './gradlew dependencyCheckAnalyze --no-daemon'
}
}
}
post {
always {
dependencyCheckPublisher(
pattern: '**/build/reports/dependency-check/dependency-check-report.xml'
)
}
failure {
slackSend(
color: 'danger',
message: "🔐 Security vulnerabilities found: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
)
}
}
}- Manage Jenkins → Credentials → Add Credential
- Kind:
Secret text - ID:
nvd-api-key - Get key from: https://nvd.nist.gov/developers/request-an-api-key
- Install plugin in Jenkins OWASP Dependency-Check
Issues Encountered
dependencyCheckPublisher not found
→ Install the OWASP Dependency-Check Plugin in Jenkins UI: Manage Jenkins → Plugins → Available
Gradle Daemon not inheriting env variables from withCredentials
→ Wrap with withEnv to pass variables into the Daemon process
-PnvdApiKey=$NVD_API_KEY broken by shell & in URL
→ Switched to withEnv + System.getenv() in build.gradle instead of -P property
403 errors from NVD despite valid key
→ Jenkins runs in Docker; tested with curl from inside container – IP not blocked, key valid. Root cause was plugin version 9.0.9 having an API key bug. Fixed by upgrading to 12.1.0.
First run took ~22 minutes
→ Normal – NVD database has ~238k records. Subsequent runs take ~1 minute thanks to local cache at /var/jenkins_home/dependency-check-data.
TODO:
Add a separate weekly job to run dependencyCheckUpdate (keep DB fresh without slowing every build)
