ITADN
clj-holmes/clj-watson
clj-holmes/clj-watson · 文件 下载 ZIP
文件最后提交记录最后更新时间
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

clj-watson

一个用于检查存在漏洞依赖项的 Clojure 工具

clj-watson 是一个软件成分分析(SCA)工具,它可以:

  1. 扫描在 Clojure deps.edn 文件中指定的依赖项
  2. 查找存在漏洞的直接依赖项和传递依赖项
  3. 生成一份报告,包含所有有助于您理解漏洞如何在您的软件中显现的信息

自 6.1.0 版本起,clj-watson 还可以通过显式指定的 类路径(classpath)来检查依赖项,这在 deps.edn 不可用或不是 主要依赖项来源的场景中非常有用,例如 Leiningen 项目。

clj-watson 可以为发现的漏洞提供修复建议, 并且可以针对 NIST 国家漏洞数据库(NVD) (默认)和 GitHub 安全公告数据库 (实验性)进行检查。

[!IMPORTANT] 我们强烈建议您始终使用 clj-watson 的最新版本。 旧版本可能无法检测当前的漏洞,甚至可能由于使用现已过时的策略而直接失败。

快速入门

  1. 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"}

  1. 设置您的 NVD API 密钥

  2. 可选地 配置 OSS Index / Sonatype Guide,如果未配置 API 令牌,则现在已禁用。

  3. 按如下方式运行 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:

  1. 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/).
  2. Scans JARs from dependencies specified in your deps.edn
  3. Composes a Common Platform Enumeration (CPE) based on your dependencies
  4. Returns any matching vulnerabilities

clj-watson 随后将这些发现报告给您,可选地附带 潜在修复措施

NIST NVD API

[!IMPORTANT] NIST NVD 数据源通过严格限制匿名请求的速率来阻止未使用 API 密钥的访问。 因此,请申请一个密钥并使用它。

申请 API 密钥](https://github.com/dependency-check/DependencyCheck/tree/main?tab=readme-ov-file#nvd-api-key-highly-recommended)很容易。

您可以通过以下方式指定您的密钥:

  1. 命令行上的 nvd.api.key Java 系统属性
  2. 或者,CLJ_WATSON_NVD_API_KEY 环境变量
  3. 或者,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:

  1. login to your Sonatype Guide account (or create a new one) at https://guide.sonatype.com/
  2. create a new API token (which will start with sonatype_pat_)
  3. update your credentials so the password is that new token, instead of your old OSS Index password

要启用 OSS Index,您需要 Sonatype Guide API 令牌

  1. 在命令行上指定 analyzer.ossindex.password Java 系统属性
  2. 或者,指定 CLJ_WATSON_ANALYZER_OSSINDEX_PASSWORD 环境变量
  3. 或者,在您的 clj-watson.properties 文件中添加 analayzer.ossindex.password 条目

[!CAUTION] 妥善保管您的 Sonatype Guide API token 是您的责任。 请勿将其提交到任何版本控制系统中。

[!TIP] 如果您想显式禁用 OSS Index 分析并消除 DependencyCheck 关于缺少凭据的警告,请指定:

  1. 在命令行上作为 Java 系统属性指定 analyzer.ossindex.enabled=false
  2. CLJ_WATSON_ANALYZER_OSSINDEX_ENABLED=false 环境变量
  3. 或在您的 clj-watson.properties 文件中指定 analyzer.ossindex.enabled=false

指定 DependencyCheck 选项

在以下所有示例中,请将 <your ...> 替换为您的实际值。

您可以混合搭配,优先级从高到低依次为:

  1. Java System Properties 在命令行上指定。

    Example: -J-Dnvd.api.key=<your nvd nist api key here>

  2. 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-watsonCLJ_WATSON_ 开头的环境变量转换为 DependencyCheck 系统属性。例如,CLJ_WATSON_NVD_API_KEY 转换为 nvd.api.key 系统属性。 对于包含下划线的系统属性,请指定两个下划线,例如 data.file_name 表示为 CLJ_WATSON_DATA_FILE__NAME。 3. Properties Fileclj-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 升级到 v2clj-watson 将尝试查找一个使用 dependency-bdependency-a 版本,该版本使用版本为 v2dependency-c,然后 clj-watson 将建议更新 dependency-a

{dependency-a {:mvn/version "v4"}}

如果 clj-watson 未找到满足此条件的 dependency-bdependency-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.010.0 的数字,用于传达漏洞的严重性。 存在多种不同的分数,但 clj-watson 始终仅报告和使用基础分数。

多年来,CVSS 已经过多次修订。 截至本文撰写时,您可以预期看到版本 2.03.03.14.0。 有时,单个漏洞会指定来自多个 CVSS 版本的分数。 为了谨慎起见,clj-watson 始终使用并报告最高的基础分数。

如果您对其他分数感兴趣,您可以随时在 NVD NIST 网站上查看 CVE,例如:https://nvd.nist.gov/vuln/detail/CVE-2022-21724。

严重性为 lowmediumhighcritical,并基于 CVSS 分数。 请参阅 NVD NIST 网站描述以获取详细信息

[!TIP] 实验性的 github-advisory 策略存在一些差异:

  • 除了 medium 可以返回严重性为 moderate,其等同于 mediumclj-watson 始终将 moderate 转换为 medium 用于 github-advisory
  • 它仅填充来自单个 CVSS 版本的分数。
  • 它并不总是填充 CVSS 分数,或者使用 0.0 进行填充。

因发现而失败

默认情况下,clj-watson0 退出。

您可以选择让 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 使用 SLFJ4Logback 来收集并过滤其依赖项中有意义的日志输出。 该输出会写入 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 .

Copyright © 2021-2024 Matheus Bernardes

Distributed under the Eclipse Public License version 2.0.