使用 VEX 创建异常
漏洞可利用性交换(VEX)是一种用于记录软件包或产品上下文中漏洞的标准格式。 Docker Scout 支持 VEX 文档,用于为镜像中的漏洞创建 豁免。
注意
您还可以通过 Docker Scout 仪表板或 Docker Desktop 创建例外项。图形用户界面提供了友好的操作界面,便于为多个镜像管理例外项。您还可以一次性为多个镜像,或整个组织创建例外项。更多详情,请参阅 通过图形界面创建例外项。
前提条件
要使用 OpenVEX 文档创建例外,您需要:
- Docker Desktop 的最新版本或 Docker Scout CLI 插件
- The
vexctl命令行工具。 - The containerd 镜像存储 必须启用
- 对存储镜像的镜像仓库仓库的写入权限
VEX 简介
VEX标准由美国网络安全与基础设施安全局(CISA)下属的一个工作组制定。VEX的核心是漏洞可利用性评估,这些评估用于描述某产品中特定CVE漏洞的当前状态。VEX中可能的漏洞状态包括:
- 不受影响:无需针对此漏洞采取任何修复措施。
- 受影响:建议采取措施修复或缓解此漏洞。
- 已修复:这些产品版本包含针对该漏洞的修复程序。
- 正在调查中:目前尚不清楚这些产品版本是否受到该漏洞的影响。后续版本中将提供更新信息。
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 软件包中,因此
--subcomponentsPURL 是 npm 软件包名称及版本 (pkg:npm/express@4.17.1) 的标识符。如果同一漏洞存在于多个软件包中,
vexctl允许您在单个create命令中多次指定--subcomponents标志。您也可以省略
--subcomponents,此时 VEX 声明将适用于整个镜像。 --vuln- VEX声明所针对的CVE编号。
--status- 这是漏洞的状态标签,用于描述软件(
--product)与CVE(--vuln)之间的关系。在OpenVEX中,状态标签的可能取值如下:not_affectedaffectedfixedunder_investigation
在本示例中,VEX语句声明该Docker镜像
not_affected受此漏洞影响。not_affected状态是唯一一种会导致CVE被抑制的状态,即该CVE将从分析结果中被过滤掉。其他状态主要用于文档说明目的,但无法用于创建例外。有关所有可能状态标签的更多信息,请参阅OpenVEX规范中的状态标签。 --justification- 说明
not_affected状态标签,用于解释为何该产品不受该漏洞影响。在此例中,所给的说明为vulnerable_code_not_in_execute_path,表示该漏洞因产品使用方式而无法被利用。在 OpenVEX 中,状态说明可具有以下五种可能值:
component_not_presentvulnerable_code_not_presentvulnerable_code_not_in_execute_pathvulnerable_code_cannot_be_controlled_by_adversaryinline_mitigations_already_exist
有关这些值及其定义的更多信息,请参阅 OpenVEX 规范中的 状态说明。
--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 文档是否格式良好并产生预期结果,请在 CLI 中使用 docker scout cves 命令配合 --vex-location 标志,对本地镜像分析应用 VEX 文档。
以下命令将调用本地镜像分析,该分析将结合指定位置中的所有 VEX 文档,并使用 --vex-location 标志。在此示例中,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 文档中使用
justification、impact_statement和其他字段以及何时使用。以不正确的方式指定这些内容会导致文档无效。请确保您的 VEX 文档符合 OpenVEX 规范。
将 VEX 文档附加到镜像
创建 VEX 文档后, 您可以通过以下方式将其附加到镜像中:
一旦添加,您就无法从镜像中移除 VEX 文档。对于作为证明(attestation)附加的文档,您可以创建一个新的 VEX 文档并将其再次附加到镜像。这样做将覆盖以前的 VEX 文档(但不会移除该证明)。对于 VEX 文档已嵌入镜像文件系统的镜像,您需要重新构建镜像才能更改 VEX 文档。
证书认证
要将 VEX 文档作为证明附加,您可以使用 docker scout attestation add CLI 命令。在使用 VEX 时,使用证明是将例外附加到镜像的推荐选项。
您可以将证明附加到已推送到注册表的镜像。您无需重新构建或推送镜像。此外,将例外作为证明附加到镜像意味着消费者可以直接从注册表检查镜像的例外。
要将证明附加到镜像:
构建镜像并将其推送到仓库。
$ docker build --provenance=true --sbom=true --tag <IMAGE> --push .将例外项作为证明附加到镜像。
$ 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-totopredicateType
镜像文件系统
如果您在构建镜像之前就预先知道了例外情况,那么将 VEX 文档直接嵌入到镜像文件系统中是一个不错的选择。这相对容易;只需在您的 Dockerfile 中将 VEX 文档 COPY 到镜像中。
这种方法的缺点是你以后无法更改或更新例外情况。镜像层是不可变的,所以你放入镜像文件系统中的任何东西都会永远存在。将文档作为证明附加提供了更好的灵活性。
注意
对于具有证明的镜像,不会考虑嵌入在镜像文件系统中的 VEX 文档。如果您的镜像具有任何证明,Docker Scout 将仅在证明中查找例外情况,而不会在镜像文件系统中查找。
如果您想使用嵌入在镜像文件系统中的 VEX 文档,则必须从镜像中移除证明。请注意,来源证明可能会自动添加到镜像中。为了确保镜像中不添加任何证明,您可以在构建镜像时使用
--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 glob 模式。
该文件存储在镜像文件系统中的位置并不重要。
请注意,复制的文件必须是最终镜像文件系统的一部分, 对于多阶段构建,文档必须保留在最终阶段中。