Vulnerable and Outdated Components are a top 10 OWASP security threat to applications. To mitigate this risk, there’s a commonly used OWASP dependency-check to scan software to identify the use of known vulnerable components.
Local NVD copy
One important aspect to know about running dependency-check, is it’s reliance on a local copy of the National Vulnerability Database.
OWASP dependency-check maintains a local copy of the NVD CVE data hosted by NIST. By default, a local H2 database instance is used. As each instance maintains its own copy of the NVD the machine will need access to nvd.nist.gov in order to download the NVD data feeds. While the initial download of the NVD data feed is large, if after the initial download the tool is run at least once every seven days only two small XML files containing the recent modifications will need to be downloaded.
And indeed, when running
mvn org.owasp:dependency-check-maven:update-only for the first time, you will find it downloads vulnerabilities for a couple of minutes.
[INFO] Checking for updates [INFO] NVD CVE requires several updates; this could take a couple of minutes. [INFO] Download Started for NVD CVE - 2002 [INFO] Download Complete for NVD CVE - 2002 (1697 ms) [INFO] Processing Started for NVD CVE - 2002 [INFO] Processing Complete for NVD CVE - 2002 (3818 ms) [INFO] Download Started for NVD CVE - 2003 [INFO] Download Complete for NVD CVE - 2003 (1062 ms) [INFO] Processing Started for NVD CVE - 2003 [INFO] Processing Complete for NVD CVE - 2003 (807 ms) ...
This local copy is stored in
~/.m2/repository/org/owasp/dependency-check-data by default, which needs to be cached to prevent repeated downloads taking excessive time, and potentially leading to
HTTP/429 Too many requests.
Notice how the local copy is stored in the local Maven repository.
This will work fine for simple use cases, such as your own machine, or a long lived build server.
But it might not be ideal for more fleeting CI environments, where you have to explicitly cache
~/.m2/repository, typically per project.
At present the database takes up ~166MB, so any duplication per project quickly adds up to both storage needs, and cache transfer times per build.
There’s also the option to use a database server, but this requires infrastructure to maintain and keep available, for risk of breaking your builds. The documentation itself starts out with the following message, which is also not very encouraging.
WARNING : This discusses an advanced setup and you may run into issues.
NVD cached in Docker image
We propose to store the NVD data in a custom Docker image, updated on a weekly schedule, and used as CI image for the OWASP dependency check CI step.
To start, we create a Dockerfile based on Maven, and within that image populate the NVD copy.
FROM maven:3.8-eclipse-temurin-17-alpine (1) RUN mvn org.owasp:dependency-check-maven:update-only \ (2) -DdataDirectory=/owasp \ (3) && rm -rf /root/.m2/ (4)
|1||We extend from the Maven base image, to ensure
|3||We store the data in
|4||We remove the
Next we create a build pipeline to push this container image to the GitLab container registry.
# Adapted from: # https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml container_registry: image: docker:latest stage: build services: # Required for Docker; not available on RedHat OpenShift - docker:dind script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" . - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" # Push to latest tag only from main branch docker-push-latest: image: docker:latest stage: deploy script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker pull "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" - docker tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" "$CI_REGISTRY_IMAGE" - docker push "$CI_REGISTRY_IMAGE" only: variables: - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Finally, we add a CI/CD Pipeline Schedule to run once a week, to stay within the seven day limit mentioned previously. That way we always have a mostly up to date NVD available, and individual scans will at most download two small XML files containing recent modifications. If you want you can schedule the pipeline once every four hours, during working hours, to make your scans work offline as much as possible.
You will likely want to configure a periodic clean up of image tags,
which is available under
Dependency check projects through GitLab CI
With the custom owasp-dependency-check image built and periodically pushed to GitLab Container registry, you can now use it in your, hopefully shared, GitLab CI pipelines.
The below build step will use the custom image to perform a scan of your
pom.xml, and report on any vulnerabilities.
variables: MAVEN_REPOSITORY: $CI_PROJECT_DIR/.m2/repository/ owasp_dependency_check: stage: .post (1) needs:  (2) image: registry.gitlab.com/acme/containers/owasp-dependency-check:latest (3) script: - mvn org.owasp:dependency-check-maven:check -DdataDirectory=/owasp -DfailBuildOnCVSS=8 (4) artifacts: when: always paths: - target/dependency-check-report.html (5)
|1||We run the check as part of the final
|2||An empty array for
|3||We refer to the latest tag of our custom owasp dependency check container.|
|4||We execute the owasp dependency check, with the same
|5||We make the HTML report available for further inspection.|
Reading the reports
When running the above build step you might see something like the following messages in the logs.
53157 [INFO] Writing report to: /builds/ACME/archiver/target/dependency-check-report.html 53549 [WARNING] One or more dependencies were identified with known vulnerabilities in archiver: log4j-api-2.17.2.jar (pkg:firstname.lastname@example.org, cpe:2.3:a:apache:log4j:2.17.2:*:*:*:*:*:*:*) : CVE-2022-33915 spring-security-crypto-5.7.2.jar (pkg:email@example.com, cpe:2.3:a:pivotal_software:spring_security:5.7.2:*:*:*:*:*:*:*, cpe:2.3:a:vmware:spring_security:5.7.2:*:*:*:*:*:*:*) : CVE-2020-5408 tomcat-embed-core-9.0.64.jar (pkg:firstname.lastname@example.org, cpe:2.3:a:apache:tomcat:9.0.64:*:*:*:*:*:*:*, cpe:2.3:a:apache_tomcat:apache_tomcat:9.0.64:*:*:*:*:*:*:*) : CVE-2022-34305 See the dependency-check report for more details. 53872 [INFO] ------------------------------------------------------------------------ 53872 [INFO] BUILD SUCCESS 53872 [INFO] ------------------------------------------------------------------------
Notice how this check did identify known vulnerabilities, but none exceeded the
failBuildOnCVSS value of
You can ofcoure set this to a suitable value for your organization and needs, as this is just an example.
The full report allows you to inspect the identified vulnerabilities, and potentially ignore false positives by passing a suppression file to the dependency check command.