使用 VEX 建立例外狀況

漏洞可利用性交換 (Vulnerability Exploitability eXchange, VEX) 是一種標準格式,用於記錄軟體套件或產品環境中的漏洞。Docker Scout 支援使用 VEX 文件來為映像檔中的漏洞建立例外

注意

您也可以使用 Docker Scout 儀表板或 Docker Desktop 建立例外。圖形化介面 (GUI) 提供了一個易於操作的介面來建立例外,並且可以輕鬆管理多個映像檔的例外。它還允許您一次為多個映像檔或整個組織建立例外。有關更多資訊,請參閱使用 GUI 建立例外

先決條件

若要使用 OpenVEX 文件建立例外,您需要:

  • 最新版本的 Docker Desktop 或 Docker Scout CLI 外掛程式
  • vexctl 命令列工具。
  • 必須啟用 containerd 映像檔儲存庫
  • 對儲存映像檔的註冊表 (registry) 儲存庫具有寫入權限

VEX 簡介

VEX 標準由美國網路安全與基礎設施安全局 (CISA) 的工作小組定義。VEX 的核心是可利用性評估。這些評估描述了給定產品的 CVE 狀態。VEX 中可能的漏洞狀態為:

  • Not affected(不受影響):無需針對此漏洞進行修復。
  • Affected(受影響):建議採取行動來修復或解決此漏洞。
  • Fixed(已修復):這些產品版本包含該漏洞的修復程式。
  • Under investigation(調查中):尚未得知這些產品版本是否受到該漏洞影響。後續版本將提供更新。

VEX 有多種實作方式和格式。Docker Scout 支援 OpenVex 實作。無論具體實作方式為何,核心概念都是一樣的:提供一個描述漏洞影響的框架。無論實作方式如何,VEX 的關鍵組成部分包括:

VEX 文件
一種用於儲存 VEX 陳述的安全諮詢類型。文件的格式取決於特定的實作。
VEX 陳述
描述產品中漏洞的狀態、是否可利用以及是否有修復問題的方法。
理由與影響
根據漏洞狀態,陳述包含解釋產品為何受影響或不受影響的理由或影響說明。
行動陳述
描述如何修復或減輕漏洞。

vexctl 範例

以下範例指令建立一個 VEX 文件,聲明:

  • 此 VEX 文件描述的軟體產品是 Docker 映像檔 example/app:v1
  • 該映像檔包含 npm 套件 express@4.17.1
  • 該 npm 套件受已知漏洞影響:CVE-2022-24999
  • 該映像檔不受此 CVE 影響,因為在執行此映像檔的容器中,從未執行過該脆弱程式碼
$ vexctl create \
  --author="author@example.com" \
  --product="pkg:docker/example/app@v1" \
  --subcomponents="pkg:npm/express@4.17.1" \
  --vuln="CVE-2022-24999" \
  --status="not_affected" \
  --justification="vulnerable_code_not_in_execute_path" \
  --file="CVE-2022-24999.vex.json"

以下是此範例中選項的說明:

--author
VEX 文件作者的電子郵件。
--product
Docker 映像檔的套件 URL (PURL)。PURL 是以標準化格式識別映像檔的識別碼,定義於 PURL 規範中。

Docker 映像檔 PURL 字串以 pkg:docker 類型前綴開頭,後面接著映像檔儲存庫和版本(映像檔標籤或 SHA256 摘要)。與版本指定為 example/app:v1 的映像檔標籤不同,在 PURL 中,映像檔儲存庫和版本由 @ 分隔。

--subcomponents
映像檔中脆弱套件的 PURL。在此範例中,漏洞存在於 npm 套件中,因此 --subcomponents PURL 是該 npm 套件名稱和版本的識別碼 (pkg:npm/express@4.17.1)。

如果同一個漏洞存在於多個套件中,vexctl 允許您在單個 create 指令中多次指定 --subcomponents 旗標。

您也可以省略 --subcomponents,這種情況下,VEX 陳述將適用於整個映像檔。

--vuln
VEX 陳述所處理的 CVE ID。
--status
這是漏洞的狀態標籤。這描述了軟體 (--product) 與 CVE (--vuln) 之間的關係。OpenVEX 中狀態標籤的可能值為:
  • not_affected
  • affected
  • fixed
  • under_investigation

在此範例中,VEX 陳述斷言該 Docker 映像檔 not_affected(不受影響)該漏洞。not_affected 狀態是唯一會導致 CVE 被抑制(從分析結果中過濾掉該 CVE)的狀態。其他狀態對於文件記錄很有用,但它們不能用於建立例外。有關所有可能狀態標籤的更多資訊,請參閱 OpenVEX 規範中的狀態標籤 (Status Labels)

--justification
證明 not_affected 狀態標籤的合理性,說明為什麼產品不受該漏洞影響。在此案例中,給出的理由是 vulnerable_code_not_in_execute_path,表示該漏洞在產品的使用方式中無法被執行。

在 OpenVEX 中,狀態理由可以具有以下五個可能值之一:

  • component_not_present
  • vulnerable_code_not_present
  • vulnerable_code_not_in_execute_path
  • vulnerable_code_cannot_be_controlled_by_adversary
  • inline_mitigations_already_exist

有關這些值及其定義的更多資訊,請參閱 OpenVEX 規範中的狀態理由 (Status Justifications)

--file
VEX 文件輸出的檔名

JSON 文件範例

以下是此指令生成的 OpenVEX JSON

{
  "@context": "https://openvex.dev/ns/v0.2.0",
  "@id": "https://openvex.dev/docs/public/vex-749f79b50f5f2f0f07747c2de9f1239b37c2bda663579f87a35e5f0fdfc13de5",
  "author": "author@example.com",
  "timestamp": "2024-05-27T13:20:22.395824+02:00",
  "version": 1,
  "statements": [
    {
      "vulnerability": {
        "name": "CVE-2022-24999"
      },
      "timestamp": "2024-05-27T13:20:22.395829+02:00",
      "products": [
        {
          "@id": "pkg:docker/example/app@v1",
          "subcomponents": [
            {
              "@id": "pkg:npm/express@4.17.1"
            }
          ]
        }
      ],
      "status": "not_affected",
      "justification": "vulnerable_code_not_in_execute_path"
    }
  ]
}

理解 VEX 文件應如何構建可能有點複雜。OpenVEX 規範描述了格式以及文件和陳述的所有可能屬性。有關完整詳細資訊,請參閱規範以了解更多關於可用欄位以及如何建立格式正確的 OpenVEX 文件的資訊。

若要了解更多關於 vexctl CLI 工具的可用旗標、語法以及安裝方法,請參閱 vexctl GitHub 儲存庫

驗證 VEX 文件

若要測試您建立的 VEX 文件是否格式正確並產生預期結果,請使用 docker scout cves 指令並加上 --vex-location 旗標,將 VEX 文件應用於使用 CLI 的本機映像檔分析。

以下指令會執行本機映像檔分析,並使用 --vex-location 旗標合併指定位置的所有 VEX 文件。在此範例中,指示 CLI 在目前的工作目錄中尋找 VEX 文件。

$ docker scout cves <IMAGE> --vex-location .

docker scout cves 指令的輸出會顯示結果,並將在 --vex-location 位置下找到的任何 VEX 陳述納入結果中。例如,狀態為 not_affected 的 CVE 會從結果中過濾掉。如果輸出似乎沒有考慮 VEX 陳述,這表示 VEX 文件可能在某方面無效。

需要注意的事項包括:

  • Docker 映像檔的 PURL 必須以 pkg:docker/ 開頭,後接映像檔名稱。
  • 在 Docker 映像檔 PURL 中,映像檔名稱和版本由 @ 分隔。名為 example/myapp:1.0 的映像檔其 PURL 為:pkg:docker/example/myapp@1.0
  • 記得指定 author(這是 OpenVEX 中的必填欄位)
  • OpenVEX 規範描述了何時以及如何使用 VEX 文件中的 justificationimpact_statement 和其他欄位。以不正確的方式指定這些欄位會導致文件無效。請確保您的 VEX 文件符合 OpenVEX 規範。

將 VEX 文件附加到映像檔

建立 VEX 文件後,您可以透過以下方式將其附加到您的映像檔:

一旦 VEX 文件被新增到映像檔中,您就無法將其移除。對於作為證明附加的文件,您可以建立新的 VEX 文件並再次將其附加到映像檔。這樣做會覆蓋先前的 VEX 文件(但不會移除證明)。對於將 VEX 文件嵌入映像檔檔案系統的映像檔,您需要重新建置映像檔才能更改 VEX 文件。

證明 (Attestation)

若要將 VEX 文件附加為證明,您可以使用 docker scout attestation add CLI 指令。使用 VEX 時,建議使用證明來將例外附加到映像檔。

您可以將證明附加到已經推送到註冊表的映像檔。您無需再次建置或推送映像檔。此外,將例外作為證明附加到映像檔意味著使用者可以直接從註冊表檢查映像檔的例外。

若要將證明附加到映像檔:

  1. 建置映像檔並將其推送到註冊表。

    $ docker build --provenance=true --sbom=true --tag <IMAGE> --push .
    
  2. 將例外作為證明附加到映像檔。

    $ docker scout attestation add \
      --file <cve-id>.vex.json \
      --predicate-type https://openvex.dev/ns/v0.2.0 \
      <IMAGE>
    

    此指令的選項為:

    • --file:VEX 文件所在位置與檔名
    • --predicate-type:OpenVEX 的 in-toto predicateType

映像檔檔案系統

如果您在建置映像檔之前就知道例外狀況,將 VEX 文件直接嵌入映像檔檔案系統是一個不錯的選擇。這相當簡單;只需在 Dockerfile 中使用 COPY 將 VEX 文件複製到映像檔中即可。

這種方法的缺點是您以後無法更改或更新例外。映像檔層是不可變的,因此您放入映像檔檔案系統中的任何內容都將永久存在。將文件作為證明附加提供了更好的靈活性。

注意

嵌入在映像檔檔案系統中的 VEX 文件不會被考慮用於具有證明的映像檔。如果您的映像檔有任何證明,Docker Scout 將僅在證明中尋找例外,而不會在映像檔檔案系統中尋找。

如果您想使用嵌入在映像檔檔案系統中的 VEX 文件,您必須移除映像檔中的證明。請注意,來源證明 (provenance attestations) 可能會自動為映像檔新增。為了確保沒有證明被新增到映像檔,您可以在建置映像檔時使用 --provenance=false--sbom=false 旗標明確停用 SBOM 和來源證明。

若要將 VEX 文件嵌入映像檔檔案系統,請在映像檔建置過程中將文件 COPY 到映像檔中。以下範例顯示如何將建置內容中 .vex/ 下的所有 VEX 文件複製到映像檔中的 /var/lib/db

# syntax=docker/dockerfile:1

FROM alpine
COPY .vex/* /var/lib/db/

VEX 文件的檔名必須符合 *.vex.json 萬用字元模式。將檔案儲存在映像檔檔案系統的何處並不重要。

請注意,複製的檔案必須是最終映像檔檔案系統的一部分。對於多階段建置,文件必須保留在最終階段。

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.