From c2349f587d53e3599bbcc34c1a7b3340f7ec160e Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Tue, 19 Dec 2023 13:08:03 -0800 Subject: [PATCH] Switch to NVD API and update dependencies (#41) * update dependencies * remove todo comment * add -w / --clj-watson-properties option this allows for a properties file that **merges** additional properties into the defaults, making it easier to customize watson's behavior * move toward v5.0.0 this uses the 9.0.x DependencyCheck and requires an API key provided via the clj-watson.properties file --------- Co-authored-by: Matheus Bernardes <12648924+mthbernardes@users.noreply.github.com> --- .gitignore | 2 ++ README.md | 22 ++++++++++++++++++++++ deps.edn | 18 +++++++++--------- resources/dependency-check.properties | 19 ++++++++++++++++--- src/clj_watson/controller/deps.clj | 6 +++--- src/clj_watson/controller/remediate.clj | 4 ++-- src/clj_watson/diplomat/dependency.clj | 10 +++++----- 7 files changed, 59 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 8c5e1a4..e90438b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ pom.xml pom.xml.asc profiles.clj target/ +.lsp/ +.portal/ \ No newline at end of file diff --git a/README.md b/README.md index c1b6007..1078593 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,28 @@ clj-watson supports two methods for vulnerabilities scan. ### dependency-check [dependency-check](https://github.com/jeremylong/DependencyCheck) is the most used method around the clojure/java sca tools, it downloads all vulnerabilities from nvd and stores it in a database (located in `/tmp/db`), compose a [cpe](https://nvd.nist.gov/products/cpe) based on the dependencies, scans all jars in the classpath and matches vulnerabilities using it. +#### NIST NVD API + +As of version v5.0.0, `clj-watson` uses +[`DependencyCheck` 9.0.x](https://github.com/jeremylong/DependencyCheck/tree/main?tab=readme-ov-file#900-upgrade-notice) +which switches from the earlier NVD data feeds to the new NIST NVD API. + +This new API heavily throttles anonymous requests, so it is +[highly recommended to get an API key](https://github.com/jeremylong/DependencyCheck/tree/main?tab=readme-ov-file#nvd-api-key-highly-recommended) +in order to use the API efficiently. + +Read the [NIST NVD announcement](https://nvd.nist.gov/general/news/API-Key-Announcement) for more information. + +Once you have an API key, you can provide it to `clj-watson` via the `nvd.api.key` +property in the optional `clj-watson.properties` file, either on the classpath +you use to run `clj-watson` or via the `-w` / `--clj-watson-properties` +command-line option: + +``` +# clj-watson.properties file +nvd.api.key=...your key here... +``` + ### Github advisory database [experimental] It doesn't need to download a database since it uses the [github advisory database](https://github.com/advisories) via the [graphql api](https://docs.github.com/en/graphql/reference/objects#securityvulnerability), matches are made via package name. But there's a requirements to use it, it's necessary to generate a [Github PAT (Personal Access Token)](https://docs.github.com/en/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql) to access graphql api or if you use Github actions it's possible to use their Github token. diff --git a/deps.edn b/deps.edn index 529e99d..77eb80c 100644 --- a/deps.edn +++ b/deps.edn @@ -1,15 +1,15 @@ {:deps {org.clojure/clojure {:mvn/version "1.11.1"} - version-clj/version-clj {:mvn/version "2.0.2"} - clj-http/clj-http {:mvn/version "3.12.3"} - cheshire/cheshire {:mvn/version "5.11.0"} + borkdude/edamame {:mvn/version "1.3.23"} + cheshire/cheshire {:mvn/version "5.12.0"} cli-matic/cli-matic {:mvn/version "0.5.4"} + clj-http/clj-http {:mvn/version "3.12.3"} clj-time/clj-time {:mvn/version "0.15.2"} - selmer/selmer {:mvn/version "1.12.55"} - org.slf4j/slf4j-nop {:mvn/version "2.0.6"} - borkdude/edamame {:mvn/version "1.0.16"} - org.clojure/tools.deps.alpha {:mvn/version "0.15.1254"} - org.owasp/dependency-check-core {:mvn/version "7.4.4"} - org.apache.maven.resolver/maven-resolver-transport-http {:mvn/version "1.9.2"}} + org.apache.maven.resolver/maven-resolver-transport-http {:mvn/version "1.9.18"} + org.clojure/tools.deps {:mvn/version "0.18.1374"} + org.owasp/dependency-check-core {:mvn/version "9.0.6"} + org.slf4j/slf4j-nop {:mvn/version "2.0.9"} + selmer/selmer {:mvn/version "1.12.59"} + version-clj/version-clj {:mvn/version "2.0.2"}} :mvn/repos {"central" {:url "https://repo1.maven.org/maven2/"} "clojars" {:url "https://repo.clojars.org/"}} diff --git a/resources/dependency-check.properties b/resources/dependency-check.properties index 5c5c10c..f817b20 100644 --- a/resources/dependency-check.properties +++ b/resources/dependency-check.properties @@ -1,5 +1,6 @@ -odc.application.name=${pom.name} -odc.application.version=${pom.version} +# replaced ${pom.*} with actual values: +odc.application.name=clj-watson +odc.application.version=5.0.0 odc.autoupdate=true odc.analysis.timeout=30 odc.settings.mask=.*password.*,.*token.* @@ -20,6 +21,18 @@ data.driver_name=org.h2.Driver proxy.disableSchemas=true +# nvd.api.key must be provided by the user: +#nvd.api.key=... +nvd.api.check.validforhours=12 +nvd.api.datafeed.startyear=2002 +nvd.api.datafeed.validfordays=7 +nvd.api.delay=2000 +nvd.api.max.retry.count=10 +# unused nvd.api.* keys: +#nvd.api.datafeed.url= +#nvd.api.datafeed.user= +#nvd.api.datafeed.password= + cve.url.modified.validfordays=7 cve.check.validforhours=12 cve.startyear=2002 @@ -103,4 +116,4 @@ analyzer.vulnerabilitysuppression.enabled=true updater.nvdcve.enabled=true updater.versioncheck.enabled=true analyzer.versionfilter.enabled=true -analyzer.artifactory.enabled=false \ No newline at end of file +analyzer.artifactory.enabled=false diff --git a/src/clj_watson/controller/deps.clj b/src/clj_watson/controller/deps.clj index cc10f39..b30a29a 100644 --- a/src/clj_watson/controller/deps.clj +++ b/src/clj_watson/controller/deps.clj @@ -1,8 +1,8 @@ (ns clj-watson.controller.deps (:require [clojure.set :refer [rename-keys]] - [clojure.tools.deps.alpha :as deps] - [clojure.tools.deps.alpha.util.maven :as maven] + [clojure.tools.deps :as deps] + [clojure.tools.deps.util.maven :as maven] [edamame.core :refer [parse-string]]) (:import (java.io File))) @@ -50,4 +50,4 @@ (dependencies-map->dependencies-vector dependencies-physical-location))})) (comment - (parse "resources/vulnerable-deps.edn" nil)) \ No newline at end of file + (parse "resources/vulnerable-deps.edn" nil)) diff --git a/src/clj_watson/controller/remediate.clj b/src/clj_watson/controller/remediate.clj index 8383c0d..c184700 100644 --- a/src/clj_watson/controller/remediate.clj +++ b/src/clj_watson/controller/remediate.clj @@ -2,7 +2,7 @@ (:require [clj-watson.diplomat.dependency :as diplomat.dependency] [clj-watson.logic.dependency :as logic.dependency] - [clojure.tools.deps.alpha.util.maven :as maven] + [clojure.tools.deps.util.maven :as maven] [version-clj.core :as version])) (defn ^:private parent-contains-child-version? @@ -62,4 +62,4 @@ :firstPatchedVersion {:identifier "2.14.2"}}], :secure-version {:mvn/version "2.14.2"}}]) - (scan vulnerable-dependencies {:mvn/repos maven/standard-repos})) \ No newline at end of file + (scan vulnerable-dependencies {:mvn/repos maven/standard-repos})) diff --git a/src/clj_watson/diplomat/dependency.clj b/src/clj_watson/diplomat/dependency.clj index 98fa122..9661a40 100644 --- a/src/clj_watson/diplomat/dependency.clj +++ b/src/clj_watson/diplomat/dependency.clj @@ -1,9 +1,9 @@ (ns clj-watson.diplomat.dependency (:require - [clojure.tools.deps.alpha :as deps] - [clojure.tools.deps.alpha.extensions :as ext] - [clojure.tools.deps.alpha.extensions.git :as git] - [clojure.tools.deps.alpha.util.maven :as maven] + [clojure.tools.deps :as deps] + [clojure.tools.deps.extensions :as ext] + [clojure.tools.deps.extensions.git :as git] + [clojure.tools.deps.util.maven :as maven] [clojure.tools.gitlibs :as gitlibs])) (defn ^:private append-sha-when-is-git-version [dependency version] @@ -47,4 +47,4 @@ (get-latest-version! 'org.clojure/clojure {:mvn/repos maven/standard-repos}) (get-latest-version! 'io.github.clj-holmes/clj-watson {:mvn/repos maven/standard-repos}) (resolve-dependency! {:deps {'io.github.clj-holmes/clj-watson {:git/tag "v2.1.3" :git/sha "19636f2"}} - :mvn/repos maven/standard-repos})) \ No newline at end of file + :mvn/repos maven/standard-repos}))