clj-watson
一个用于检查存在漏洞依赖项的 Clojure 工具
clj-watson 是一个软件成分分析(SCA)工具,它可以:
- 扫描在 Clojure
deps.edn文件中指定的依赖项 - 查找存在漏洞的直接依赖项和传递依赖项
- 生成一份报告,包含所有有助于您理解漏洞如何在您的软件中显现的信息
自 6.1.0 版本起,clj-watson 还可以通过显式指定的
类路径(classpath)来检查依赖项,这在 deps.edn 不可用或不是
主要依赖项来源的场景中非常有用,例如 Leiningen 项目。
clj-watson 可以为发现的漏洞提供修复建议,
并且可以针对
NIST 国家漏洞数据库(NVD)
(默认)和
GitHub 安全公告数据库
(实验性)进行检查。
[!IMPORTANT] 我们强烈建议您始终使用
clj-watson的最新版本。 旧版本可能无法检测当前的漏洞,甚至可能由于使用现已过时的策略而直接失败。
快速入门
-
clj-watson可以作为别名添加,既可以按项目级别添加到您的 项目的deps.edn文件中,也可以添加到您的用户deps.edn文件中 (即~/.clojure/deps.edn或~/.config/clojure/deps.edn):;; under :aliases :clj-watson {:replace-deps {io.github.clj-holmes/clj-watson {:git/tag "v6.1.0" :git/sha "be98e4d"}} :main-opts ["-m" "clj-watson.cli"]}
您还可以添加对 org.owasp/dependency-check-core 的依赖,如果您想使用更新的版本(推荐 -- 但这会给您带来保持其更新的维护负担!)。截至 2026 年 5 月 3 日,当前版本为 {:mvn/version "12.2.2"}。
-
可选地 配置 OSS Index / Sonatype Guide,如果未配置 API 令牌,则现在已禁用。
-
按如下方式运行 clj-watson:
clojure -M:clj-watson scan -p deps.edn
首次运行 clj-watson 时,它会下载完整的漏洞数据库。
这可能需要几分钟。后续运行会快得多。
[!NOTE] 数据库存储在您本地 Maven 缓存中的 dependency-check-utils
~/.m2/repository/org/owasp/dependency-check-utils/12.2.2/data/11.0/下。 如果您删除此目录,数据库将自动重新下载。
clj-watson 也可以作为 Clojure CLI 工具安装:
clojure -Ttools install-latest :lib io.github.clj-holmes/clj-watson :as clj-watson
在设置好您的 NVD API 密钥]之后,您可以像这样运行 clj-watson:
clojure -Tclj-watson scan :deps-edn-path deps.edn
-T 工具选项关键字同时匹配长格式和别名 -M CLI 选项。 因此,这也有效:
clojure -Tclj-watson scan :p deps.edn
[!NOTE] 对于 -T 工具的使用,
:aliases(或:a)被指定为关键词(或符号)的向量,例如:a '[:foo :bar]',而对于 -M 的使用,则需多次指定,-a foo -a bar。 运行:
clojure -M:clj-watson scan --help以获取 -M 使用帮助clojure -Tclj-watson scan :help true以获取 -T 工具使用帮助
自 6.1.0 起,clj-watson 还可以通过显式指定的
类路径来检查依赖项:
clojure -Tclj-watson scan :classpath '"'$(lein classpath)'"'
[!NOTE]
:classpath的值必须是一个字符串,因此上述示例使用 shell 引号来确保lein classpath的输出作为单个字符串传递。
漏洞数据库策略
clj-watson 支持两种漏洞扫描策略:
DependencyCheck
DependencyCheck is the most widely used method among Clojure/Java SCA tools. It:
- Downloads a database of known vulnerabilities from NIST NVD, storing it locally (inside your local Maven cache, under
~/.m2/repository/org/owasp/dependency-check-utils/12.2.2/data/11.0/). - Scans JARs from dependencies specified in your
deps.edn - Composes a Common Platform Enumeration (CPE) based on your dependencies
- Returns any matching vulnerabilities
clj-watson 随后将这些发现报告给您,可选地附带 潜在修复措施。
NIST NVD API
[!IMPORTANT] NIST NVD 数据源通过严格限制匿名请求的速率来阻止未使用 API 密钥的访问。 因此,请申请一个密钥并使用它。
您可以通过以下方式指定您的密钥:
- 命令行上的
nvd.api.keyJava 系统属性 - 或者,
CLJ_WATSON_NVD_API_KEY环境变量 - 或者,
clj-watson.properties文件中的nvd.api.key条目
[!CAUTION] 妥善保管你的 nvd api key 是你的责任。 这并非极其敏感的机密,但你并不希望他人使用你的密钥。 你不希望将其提交到任何版本控制系统中。
OSS 索引配置
DependencyCheck 还可以查询 OSS Index。
[!NOTE] 当 OSS Index 开始要求身份验证时,DependencyCheck 改为在未配置凭据时自动禁用其使用。 如果您愿意,可以通过指定您的 Sonatype Guide API 令牌来重新启用它。
As of April 2026, Sonatype OSS Index migrated to Sonatype Guide, which means you need to:
- login to your Sonatype Guide account (or create a new one) at https://guide.sonatype.com/
- create a new API token (which will start with
sonatype_pat_) - update your credentials so the password is that new token, instead of your old OSS Index password
要启用 OSS Index,您需要 Sonatype Guide API 令牌:
- 在命令行上指定
analyzer.ossindex.passwordJava 系统属性 - 或者,指定
CLJ_WATSON_ANALYZER_OSSINDEX_PASSWORD环境变量 - 或者,在您的
clj-watson.properties文件中添加analayzer.ossindex.password条目
[!CAUTION] 妥善保管您的 Sonatype Guide API token 是您的责任。 请勿将其提交到任何版本控制系统中。
[!TIP] 如果您想显式禁用 OSS Index 分析并消除 DependencyCheck 关于缺少凭据的警告,请指定:
- 在命令行上作为 Java 系统属性指定
analyzer.ossindex.enabled=false- 或
CLJ_WATSON_ANALYZER_OSSINDEX_ENABLED=false环境变量- 或在您的
clj-watson.properties文件中指定analyzer.ossindex.enabled=false
指定 DependencyCheck 选项
在以下所有示例中,请将 <your ...> 替换为您的实际值。
您可以混合搭配,优先级从高到低依次为:
-
Java System Properties 在命令行上指定。
Example:
-J-Dnvd.api.key=<your nvd nist api key here> -
Environment Variables Environment variables are often the most straightforward and most secure way to provide sensitive information like API keys and credentials in CI systems.
示例:CLJ_WATSON_NVD_API_KEY=<your nvd nist api key here>
clj-watson 将 CLJ_WATSON_ 开头的环境变量转换为 DependencyCheck 系统属性。例如,CLJ_WATSON_NVD_API_KEY 转换为 nvd.api.key 系统属性。
对于包含下划线的系统属性,请指定两个下划线,例如 data.file_name 表示为 CLJ_WATSON_DATA_FILE__NAME。
3. Properties File 如 clj-watson.properties 文件中所述。
示例:oss.index.enabled=false
clj-watson 首先加载其默认的内部 dependency-check.properties,并应用来自您的 clj-watson.properties 文件的覆盖设置。clj-watson.properties 文件通过 命令行 上的 --clj-watson-properties 显式指定,或在您的类路径上自动发现。
在命令行上使用 Java 系统属性
-M 用法示例:
clojure -J-Dnvd.api.key=<your nvd nist api key here> \
-M:clj-watson scan -p deps.edn
或通过类路径:
clojure -J-Dnvd.api.key=<your nvd nist api key here> \
-M:clj-watson scan --classpath $(lein classpath)
启用 OSS Index 后:
clojure -J-Dnvd.api.key=<your nvd nist api key here> \
-J-Danalyzer.ossindex.password=<your sonatype guide api token here> \
-M:clj-watson scan -p deps.edn
示例 -T 工具用法:
clojure -J-Dnvd.api.key=<your nvd nist api key here> \
-Tclj-watson scan :p deps.edn
启用 OSS Index 时:
clojure -J-Dnvd.api.key=<your nvd nist api key here> \
-J-Danalyzer.ossindex.password=<your sonatype guide api token here> \
-Tclj-watson scan :p deps.edn
[!CAUTION] 你可以在
:jvm-opts下指定系统属性,位于你的deps.edn下的:clj-watson别名下,但请注意不要将机密信息提交到版本控制中。
使用环境变量
-M 用法示例:
CLJ_WATSON_NVD_API_KEY=<your nvd nist api key here> \
clojure -M:clj-watson scan -p deps.edn
启用 OSS Index:
CLJ_WATSON_NVD_API_KEY=<your nvd nist api key here> \
CLJ_WATSON_ANALYZER_OSSINDEX_PASSWORD=<your sonatype guide api token here> \
clojure -M:clj-watson scan -p deps.edn
示例 -T 工具用法:
CLJ_WATSON_NVD_API_KEY=<your nvd nist api key here> \
clojure -Tclj-watson scan :p deps.edn
启用 OSS Index 时:
CLJ_WATSON_NVD_API_KEY=<your nvd nist api key here> \
CLJ_WATSON_ANALYZER_OSSINDEX_PASSWORD=<your sonatype guide api token here> \
clojure -Tclj-watson scan :p deps.edn
[!NOTE] 在 Bash 中,你也可以在运行命令之前导出环境变量,例如:
export CLJ_WATSON_NVD_API_KEY=<your nvd nist api key here> export CLJ_WATSON_ANALYZER_OSSINDEX_PASSWORD=<your sonatype guide api token here> clojure -M:clj-watson scan -p deps.edn
使用 clj-watson.properties 文件
在你的 clj-watson.properties 文件中指定你的选项:
# clj-watson.properties file
nvd.api.key=<your nvd nist api key here>
或者,启用 OSS Index 后:
# clj-watson.properties file
nvd.api.key=<your nvd nist api key here>
analyzer.ossindex.password=<your sonatype guide api token here>
如果 clj-watson 文件位于类路径上,clj-watson.properties 将自动加载该文件,或者您可以通过 -w / --clj-watson-properties 选项在命令行中指定该文件:
-M 用法示例:
clojure -M:clj-watson scan -p deps.edn --clj-watson-properties ./clj-watson.properties
-T 用法示例:
clojure -Tclj-watson scan :p deps.edn :clj-watson-properties ./clj-watson.properties
[!CAUTION] 请注意,切勿将任何机密信息提交到版本控制系统。
GitHub Advisory Database [experimental]
这种方法无需下载数据库,因为它通过 GitHub Advisory Database 及其 GraphQL API 进行匹配,匹配依据是包名称。
为了使用这种方法,需要生成一个 GitHub Personal Access Token (PAT) 以访问 GraphQL API,或者如果你使用 GitHub Actions,则可以使用 它们的 GitHub token。
需要注意的一个重要事项是,该 API 的限制为每小时/每个 PAT 5,000 次请求。
如果你创建了一个 PAT 或使用了 GitHub Action token,你可以将其设置为名为 GITHUB_TOKEN 的环境变量,clj-watson 将能够使用它。
允许列出已知的 CVE
有时,传递依赖树不在你的控制之下,并且并不总是可以覆盖存在漏洞的依赖项。
你可以通过在 classpath 中添加一个具有以下结构的 clj-watson-config.edn
配置文件,在有限期限内允许某个 CVE:
{:allow-list {:cves [{:cve-label "CVE-0000"
:expires "2000-01-01"}
{:cve-label "CVE-00000"
:expires "2000-01-01"}]}}
注意:此内容仅适用于 GitHub 建议数据库策略。
修复建议
clj-watson 与其他工具的主要区别!
由于手动修复发现的漏洞可能是一个真正令人沮丧的过程,clj-watson 提供了一种建议修复的方法。
它会对整个依赖树执行查找,检查父依赖项的最新版本是否使用了子依赖项的安全版本,直到到达直接依赖项为止。
给定以下依赖树,
[dependency-a "v1"]
[dependency-b "v1"]
[dependency-c "v1"]
其中 dependency-c 存在漏洞,修复它需要从 v1
升级到 v2,clj-watson 将尝试查找一个使用
dependency-b 的 dependency-a 版本,该版本使用版本为 v2 的 dependency-c,然后
clj-watson 将建议更新 dependency-a。
{dependency-a {:mvn/version "v4"}}
如果 clj-watson 未找到满足此条件的 dependency-b 或 dependency-a 版本,
它将建议排除:
{dependency-a {:exclusions [dependency-b]}
dependency-b {:mvn/version "v3"}}
要获取自动修复建议,请在运行 clj-watson 时指定
--suggest-fix 或 -s 选项。
安装说明
[!IMPORTANT] 您需要 设置您的 NVD API 密钥。
请参阅 快速入门 以获取概述。
工具使用
clj-watson 可以安装为 Clojure CLI 工具,如 快速入门 中所示。
这是安装最新版本并保持其更新的最简单方法
(使用 clojure -Ttools install-latest),但这意味着使用 CLI 工具的键值
EDN 风格选项,起初可能显得有点笨拙。
等效用法示例:
clojure -Tclj-watson scan '{:fail-on-result true :deps-edn-path "deps.edn" :suggest-fix true :aliases ["*"]}'
# or:
clojure -Tclj-watson scan :fail-on-result true :deps-edn-path deps.edn :suggest-fix true :aliases '[*]'
如果您对 -T 工具不熟悉,您可能会惊讶地发现,对于一些看似非异常的情况也会抛出异常。 例如,命令行上的拼写错误会显示您预期的内容(错误说明和使用帮助),但也会显示如下所示的输出:
Execution error (ExceptionInfo) at clj-watson.entrypoint/scan$fn (entrypoint.clj:75).
usage error
Full report at:
/tmp/clojure-16796860161725335561.edn
这是 -T 工具的特性,它们被设计为可以潜在地串联使用,因此会抛出异常而不是退出,从而表现出这种行为。
使用 -Sdeps 调用
另一种调用方式是通过 -Sdeps:
clojure -Sdeps '{:deps {io.github.clj-holmes/clj-watson {:git/tag "v6.1.0" :git/sha "be98e4d"}}}' \
-M -m clj-watson.cli scan -p deps.edn
CLI 选项
运行以下命令可获取可用选项的完整列表:
clojure -M:clj-watson scan --help
这将产生:
clj-watson
ARG USAGE:
scan [options..]
OPTIONS:
-p, --deps-edn-path <file> Path of deps.edn file to scan.
This option is mutually exclusive with --classpath
--classpath <classpath> The classpath to scan.
This option is mutually exclusive with --deps-edn-path
-o, --output <json|edn|stdout|stdout-simple|sarif> Output type for vulnerability findings [stdout]
-a, --aliases Include deps.edn aliases in analysis, specify '*' for all.
For multiple, repeat arg, ex: -a alias1 -a alias2
This option is not compatible with --classpath
-t, --database-strategy <dependency-check|github-advisory> Vulnerability database strategy [dependency-check]
-s, --suggest-fix Include dependency remediation suggestions in vulnerability findings. [false]
This option is not compatible with --classpath
-f, --fail-on-result When enabled, exit with non-zero on any vulnerability findings
Useful for CI/CD [false]
-c, --cvss-fail-threshold <score> Exit with non-zero when any vulnerability's CVSS base score is >= threshold
CVSS scores range from 0.0 (least severe) to 10.0 (most severe)
We interpret a score of 0.0 as suspicious
Missing or suspicious CVSS base scores are conservatively derived
Useful for CI/CD
-h, --help Show usage help
OPTIONS valid when database-strategy is dependency-check:
-w, --clj-watson-properties <file> Path of an additional, optional properties file
Overrides values in dependency-check.properties
If not specified classpath is searched for clj-watson.properties
--run-without-nvd-api-key Run without an nvd.api.key configured.
It will be slow and we cannot recommend it.
See docs for configuration. [false]
[!TIP] 如果你将
clj-watson作为工具运行,请执行:clojure -Tclj-watson scan :help true
执行
运行 clj-watson 所需的最小条件是提供 deps.edn
文件的路径,但建议同时提供 -s 选项,以便
clj-watson 尝试为发现的任何漏洞提供修复建议。
[!IMPORTANT] 你必须首先 设置你的 NVD API 密钥。
clojure -M:clj-watson scan -p deps.edn -s
...
Dependency Information
-----------------------------------------------------
NAME: dependency-e
VERSION: 1
DEPENDENCY FOUND IN:
[dependency-a]
[dependency-b]
[dependency-a]
[dependency-c]
[dependency-d]
FIX SUGGESTION: {dependency-a {:mvn/version "3"}}
Vulnerabilities
-----------------------------------------------------
SEVERITY: Information not available.
IDENTIFIERS: CVE-2022-1000000
CVSS: 7.5 (version 3.1)
PATCHED VERSION: 1.55
SEVERITY: Information not available.
IDENTIFIERS: CVE-2022-2000000
CVSS: 5.3
PATCHED VERSION: 1.55
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
CVSS 分数与严重性
通用漏洞评分系统(CVSS)分数是一个从 0.0 到 10.0 的数字,用于传达漏洞的严重性。
存在多种不同的分数,但 clj-watson 始终仅报告和使用基础分数。
多年来,CVSS 已经过多次修订。
截至本文撰写时,您可以预期看到版本 2.0、3.0、3.1 和 4.0。
有时,单个漏洞会指定来自多个 CVSS 版本的分数。
为了谨慎起见,clj-watson 始终使用并报告最高的基础分数。
如果您对其他分数感兴趣,您可以随时在 NVD NIST 网站上查看 CVE,例如:https://nvd.nist.gov/vuln/detail/CVE-2022-21724。
严重性为 low、medium、high 或 critical,并基于 CVSS 分数。
请参阅 NVD NIST 网站描述以获取详细信息。
[!TIP] 实验性的
github-advisory策略存在一些差异:
- 除了
medium可以返回严重性为moderate,其等同于medium。clj-watson始终将moderate转换为medium用于github-advisory。- 它仅填充来自单个 CVSS 版本的分数。
- 它并不总是填充 CVSS 分数,或者使用
0.0进行填充。
因发现而失败
默认情况下,clj-watson 以 0 退出。
您可以选择让 clj-watson 在检测到漏洞时以非零值退出,这在从持续集成(CI)服务器或服务运行时可能很有用。
指定 --fail-on-result(或 -f)以在检测到任何漏洞时以非零状态退出。
用法示例:
clojure -M:clj-watson scan --deps-edn-path deps.edn --fail-on-result
clojure -Tclj-watson scan :deps-edn-path deps.edn :fail-on-result true
如需更精细的控制,请使用 --cvss-fail-threshold(或 -c)来指定用于判定失败的 CVSS 分数阈值。
当检测到的任何漏洞的分数等于或高于该阈值时,clj-watson 将汇总达到阈值的漏洞并以非零状态退出。
使用示例:
clojure -M:clj-watson scan --deps-edn-path deps.edn --cvss-fail-threshold 5.8
clojure -Tclj-watson scan :deps-edn-path deps.edn :cvss-fail-threshold 5.8
汇总示例:
CVSS fail score threshold of 5.8 met for:
Dependency Version Identifiers CVSS Score
org.apache.httpcomponents/httpclient 4.1.2 CVE-2014-3577 5.8 (version 2.0)
com.fasterxml.jackson.core/jackson-annotations 2.4.0 CVE-2018-1000873 6.5 (version 3.1)
com.fasterxml.jackson.core/jackson-core 2.4.2 CVE-2018-1000873 6.5 (version 3.1)
org.jsoup/jsoup 1.6.1 CVE-2021-37714 7.5 (version 3.1)
com.fasterxml.jackson.core/jackson-databind 2.4.2 CVE-2020-9548 9.8 (version 3.1)
org.clojure/clojure 1.8.0 CVE-2017-20189 9.8 (version 3.1)
org.codehaus.plexus/plexus-utils 3.0 CVE-2017-1000487 9.8 (version 3.1)
当分数缺失或看起来可疑时,clj-watson 会保守地推导出一个分数,并说明其推导方式(参见下文 httpclient):
CVSS fail score threshold of 5.8 met for:
Dependency Version Identifiers CVSS Score
org.jsoup/jsoup 1.6.1 GHSA-m72m-mhq2-9p6c CVE-2021-37714 7.5 (version 3.1)
com.fasterxml.jackson.core/jackson-databind 2.4.2 GHSA-qxxx-2pp7-5hmx CVE-2017-7525 9.8 (version 3.1)
com.mchange/c3p0 0.9.5.2 GHSA-q485-j897-qc27 CVE-2018-20433 9.8 (version 3.0)
org.clojure/clojure 1.8.0 GHSA-jgxc-8mwq-9xqw CVE-2017-20189 9.8 (version 3.1)
org.codehaus.plexus/plexus-utils 3.0 GHSA-8vhq-qq4p-grq3 CVE-2017-1000487 9.8 (version 3.1)
org.apache.httpcomponents/httpclient 4.1.2 GHSA-2x83-r56g-cv47 CVE-2012-6153 10.0 (score 0.0 suspicious - derived from High severity)
输出与日志
clj-watson 使用 SLFJ4 和 Logback 来收集并过滤其依赖项中有意义的日志输出。
该输出会写入 stderr。
它将配置和漏洞发现结果写入 stdout。
谁在使用它
您正在使用 clj-watson 吗?请告诉我们,我们会将您的项目添加到这里!
开发
nREPL
clojure -M:nREPL -m nrepl.cmdline
测试
clojure -M:test
Lint
我们使用 clojure-lsp 命令行工具 进行 lint:
clojure -M:clojure-lsp format
clojure -M:clojure-lsp clean-ns
clojure -M:clojure-lsp diagnostics
Security
我们使用 clj-holmes 检查 clj-watson 源代码中潜在存在漏洞的模式:
clj-holmes scan -p .
License and Copyright
Copyright © 2021-2024 Matheus Bernardes
Distributed under the Eclipse Public License version 2.0.