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