diff --git a/.github/dogfooding_suppressions.xml b/.github/dogfooding_suppressions.xml
index e4b902f..7d201b5 100644
--- a/.github/dogfooding_suppressions.xml
+++ b/.github/dogfooding_suppressions.xml
@@ -37,6 +37,14 @@
.*\bbcprov-jdk18on-1\.71\.jar
CVE-2023-33201
+
+ .*\bbcprov-jdk18on-1\.71\.jar
+ CVE-2023-33202
+
+
+ .*\bbcpg-jdk18on-1\.71\.jar
+ CVE-2023-33202
+
^pkg:maven/org\.codehaus\.plexus/plexus-.*$
cpe:/a:codehaus-plexus_project:codehaus-plexus
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 410113e..2cbe7c1 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -11,6 +11,8 @@ on:
jobs:
test_suite:
name: Linting and tests
+ env:
+ NVD_API_TOKEN: ${{ secrets.NVD_API_TOKEN }}
runs-on: ubuntu-latest
strategy:
matrix:
@@ -39,6 +41,8 @@ jobs:
continue-on-error: true
integration:
name: Integration test suite
+ env:
+ NVD_API_TOKEN: ${{ secrets.NVD_API_TOKEN }}
runs-on: ubuntu-latest
strategy:
matrix:
diff --git a/deps.edn b/deps.edn
index c486d52..1186431 100644
--- a/deps.edn
+++ b/deps.edn
@@ -4,7 +4,7 @@
clansi/clansi {:mvn/version "1.0.0"}
org.clojure/data.json {:mvn/version "2.4.0"}
org.slf4j/slf4j-simple {:mvn/version "2.0.9"}
- org.owasp/dependency-check-core {:mvn/version "8.4.3"}
+ org.owasp/dependency-check-core {:mvn/version "9.0.7"}
rm-hull/table {:mvn/version "0.7.1"}
trptcolin/versioneer {:mvn/version "0.2.0"}}
:mvn/repos {"central" {:url "https://repo1.maven.org/maven2/"}
diff --git a/project.clj b/project.clj
index 91c2b34..2f76733 100644
--- a/project.clj
+++ b/project.clj
@@ -7,7 +7,7 @@
[clansi "1.0.0"]
[org.clojure/data.json "2.4.0"]
[org.slf4j/slf4j-simple "2.0.9"]
- [org.owasp/dependency-check-core "8.4.3"]
+ [org.owasp/dependency-check-core "9.0.7"]
[rm-hull/table "0.7.1"]
[trptcolin/versioneer "0.2.0"]
;; Explicitly depend on a certain Jackson, consistently.
@@ -16,15 +16,15 @@
[com.fasterxml.jackson.core/jackson-annotations "2.16.0"]
[com.fasterxml.jackson.core/jackson-core "2.16.0"]
[com.fasterxml.jackson.module/jackson-module-afterburner "2.16.0"]
- [org.apache.maven.resolver/maven-resolver-transport-http "1.9.16" #_"Fixes a CVE"]
+ [org.apache.maven.resolver/maven-resolver-transport-http "1.9.18" #_"Fixes a CVE"]
[org.yaml/snakeyaml "2.2" #_"Fixes a CVE"]
- [org.apache.maven/maven-core "3.9.5" #_"Fixes a CVE"]
- [org.eclipse.jetty/jetty-client "12.0.3" #_"Fixes a CVE" :exclusions [org.slf4j/slf4j-api]]
- [org.apache.maven.resolver/maven-resolver-spi "1.9.16" #_"Satisfies :pedantic?"]
- [org.apache.maven.resolver/maven-resolver-api "1.9.16" #_"Satisfies :pedantic?"]
- [org.apache.maven.resolver/maven-resolver-util "1.9.16" #_"Satisfies :pedantic?"]
- [org.apache.maven.resolver/maven-resolver-impl "1.9.16" #_"Satisfies :pedantic?"]
- [org.apache.maven/maven-resolver-provider "3.9.5" #_"Satisfies :pedantic?"]
+ [org.apache.maven/maven-core "3.9.6" #_"Fixes a CVE"]
+ [org.eclipse.jetty/jetty-client "12.0.4" #_"Fixes a CVE" :exclusions [org.slf4j/slf4j-api]]
+ [org.apache.maven.resolver/maven-resolver-spi "1.9.18" #_"Satisfies :pedantic?"]
+ [org.apache.maven.resolver/maven-resolver-api "1.9.18" #_"Satisfies :pedantic?"]
+ [org.apache.maven.resolver/maven-resolver-util "1.9.18" #_"Satisfies :pedantic?"]
+ [org.apache.maven.resolver/maven-resolver-impl "1.9.18" #_"Satisfies :pedantic?"]
+ [org.apache.maven/maven-resolver-provider "3.9.6" #_"Satisfies :pedantic?"]
[org.codehaus.plexus/plexus-utils "4.0.0" #_"Satisfies :pedantic?"]]
:managed-dependencies [[com.google.code.gson/gson "2.10.1"]]
:scm {:url "git@github.com:rm-hull/nvd-clojure.git"}
@@ -43,10 +43,10 @@
[jonase/eastwood "1.4.0"]]
:eastwood {:add-linters [:boxed-math
:performance]}
- :dependencies [[clj-kondo "2023.10.20"]
+ :dependencies [[clj-kondo "2023.12.15"]
[commons-collections "20040616"]]}
:ci {:pedantic? :abort}
- :clj-kondo {:dependencies [[clj-kondo "2023.10.20"]]}
+ :clj-kondo {:dependencies [[clj-kondo "2023.12.15"]]}
:skip-self-check {:jvm-opts ["-Dnvd-clojure.internal.skip-self-check=true"]}}
:deploy-repositories [["clojars" {:url "https://clojars.org/repo"
:username :env/clojars_username
diff --git a/src/nvd/config.clj b/src/nvd/config.clj
index cd57454..124dba7 100644
--- a/src/nvd/config.clj
+++ b/src/nvd/config.clj
@@ -46,10 +46,15 @@
Settings$KEYS/DB_DRIVER_PATH [:database :driver-path]
Settings$KEYS/DB_CONNECTION_STRING [:database :connection-string]
Settings$KEYS/DB_USER [:database :user]
- Settings$KEYS/DB_PASSWORD [:database :password]})
-
-(def ^:private integer-mappings
- {Settings$KEYS/CVE_CHECK_VALID_FOR_HOURS [:cve :valid-for-hours]})
+ Settings$KEYS/DB_PASSWORD [:database :password]
+ Settings$KEYS/NVD_API_KEY [:nvd-api :key]
+ Settings$KEYS/NVD_API_ENDPOINT [:nvd-api :endpoint]
+ Settings$KEYS/NVD_API_DELAY [:nvd-api :delay]
+ Settings$KEYS/NVD_API_MAX_RETRY_COUNT [:nvd-api :max-retry-count]
+ Settings$KEYS/NVD_API_VALID_FOR_HOURS [:nvd-api :valid-for-hours]
+ Settings$KEYS/NVD_API_DATAFEED_URL [:nvd-api :datafeed :url]
+ Settings$KEYS/NVD_API_DATAFEED_USER [:nvd-api :datafeed :user]
+ Settings$KEYS/NVD_API_DATAFEED_PASSWORD [:nvd-api :datafeed :password]})
(def ^:private boolean-mappings
{Settings$KEYS/ANALYZER_ARCHIVE_ENABLED [:analyzer :archive-enabled]
@@ -100,7 +105,9 @@
{:exit-after-check true
:delete-config? true
:verbose-summary false
- :nvd {:analyzer {:assembly-enabled false
+ :nvd {:nvd-api {:delay 2500
+ :max-retry-count 10}
+ :analyzer {:assembly-enabled false
:archive-enabled true
:autoconf-enabled false
:bundle-audit-enabled false
@@ -187,15 +194,21 @@ You can pass an empty string for an .edn file to be automatically created."
(maybe-create-suppression-file! nvd-settings)
- (doseq [[prop path] integer-mappings]
- (.setIntIfNotNull settings prop (get-in nvd-settings path)))
-
(doseq [[prop path] boolean-mappings]
(.setBooleanIfNotNull settings prop (get-in nvd-settings path)))
(doseq [[prop path] string-mappings]
(.setStringIfNotEmpty settings prop (str (get-in nvd-settings path))))
+ (when (= ::not-found (get-in nvd-settings [:nvd-api :key] ::not-found))
+ (let [api-key (System/getenv "NVD_API_TOKEN")]
+
+ (when (or (not api-key)
+ (string/blank? api-key))
+ (throw (ex-info "No NVD API key supplied as config settings or env var." {})))
+
+ (.setString settings Settings$KEYS/NVD_API_KEY api-key)))
+
(-> project
(assoc-in [:nvd :data-directory] (.getDataDirectory settings))
(assoc :engine (Engine. settings)
diff --git a/src/nvd/report.clj b/src/nvd/report.clj
index 77614a6..854e6c9 100644
--- a/src/nvd/report.clj
+++ b/src/nvd/report.clj
@@ -22,16 +22,17 @@
(ns nvd.report
(:require
- [clojure.string :as s]
- [clojure.java.io :as io]
[clansi :refer [style]]
+ [clojure.java.io :as io]
+ [clojure.string :as s]
+ [nvd.log :as log]
[table.core :refer [table]])
(:import
- [java.util Arrays]
- [org.owasp.dependencycheck Engine]
- [org.owasp.dependencycheck.dependency Dependency Vulnerability]
- [org.owasp.dependencycheck.exception ExceptionCollection]
- [org.owasp.dependencycheck.reporting ReportGenerator]))
+ (java.util Arrays)
+ (org.owasp.dependencycheck Engine)
+ (org.owasp.dependencycheck.dependency Dependency Vulnerability)
+ (org.owasp.dependencycheck.exception ExceptionCollection)
+ (org.owasp.dependencycheck.reporting ReportGenerator)))
(def default-output-dir "target/nvd")
@@ -53,9 +54,17 @@
(let [cvss2 (.getCvssV2 vulnerability)
cvss3 (.getCvssV3 vulnerability)]
(cond
- cvss2 (.getScore cvss2)
- cvss3 (.getBaseScore cvss3)
- :else 1)))
+ cvss2 (max (double (or (.getExploitabilityScore cvss2)
+ 0))
+ (double (or (.getImpactScore cvss2)
+ 0)))
+ cvss3 (max (double (or (.getExploitabilityScore cvss3)
+ 0))
+ (double (or (.getImpactScore cvss3)
+ 0)))
+ :else (do
+ (.warn log/logger (str "No CVSS found for: " (pr-str vulnerability)))
+ 1))))
(defn- severity [^long cvssScore]
(cond