使用VEX创建异常
漏洞可利用性交换(VEX)是一种标准格式,用于在软件包或产品的背景下记录漏洞。Docker Scout支持VEX文档,为镜像中的漏洞创建例外。
注意
您还可以使用 Docker Scout 仪表板或 Docker Desktop 创建例外。图形用户界面提供了一个用户友好的界面来创建例外,并且可以轻松管理多个镜像的例外。它还允许您一次性为多个镜像或整个组织创建例外。有关更多信息,请参阅 使用 GUI 创建例外。
先决条件
要使用OpenVEX文档创建异常,您需要:
- 最新版本的Docker Desktop或Docker Scout CLI插件
-
vexctl命令行工具。 - 必须启用 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- The email of the author of the VEX document.
--product- Package URL (PURL) of the Docker image. A PURL is an identifier
for the image in a standardized format, defined in the PURL
规范.
Docker 镜像 PURL 字符串以
pkg:docker类型前缀开头,后跟镜像仓库和版本(镜像标签或 SHA256 摘要)。与镜像标签不同,在 PURL 中,镜像仓库和版本由@分隔,而不是像example/app:v1这样指定版本。 --subcomponents- PURL of the vulnerable package in the image. In this example, the
vulnerability exists in an npm package, so the
--subcomponentsPURL is the identifier for the npm package name and version (pkg:npm/express@4.17.1).如果相同的漏洞存在于多个包中,
vexctl允许你在单个create命令中多次指定--subcomponents标志。你也可以省略
--subcomponents,在这种情况下,VEX语句适用于整个图像。 --vuln- ID of the CVE that the VEX statement addresses.
--status- This is the status label of the vulnerability. This describes the
relationship between the software (
--product) and the CVE (--vuln). The possible values for the status label in OpenVEX are:not_affectedaffectedfixedunder_investigation
在这个例子中,VEX 语句断言 Docker 镜像
not_affected不受该漏洞的影响。not_affected状态是唯一会导致 CVE 被抑制的状态,即 CVE 会被从分析结果中过滤掉。其他状态对于文档记录很有用,但它们不适用于创建例外。有关所有可能的状态标签的更多信息,请参阅 状态标签 在 OpenVEX 规范中。 --justification- Justifies the
not_affectedstatus label, informing why the product is not affected by the vulnerability. In this case, the justification given isvulnerable_code_not_in_execute_path, signalling that the vulnerability can't be executed as used by the product.在OpenVEX中,状态理由可以有五种可能的值:
component_not_presentvulnerable_code_not_presentvulnerable_code_not_in_execute_pathvulnerable_code_cannot_be_controlled_by_adversaryinline_mitigations_already_exist
有关这些值及其定义的更多信息,请参阅 状态理由 在OpenVEX规范中。
--file- Filename of the VEX document output
示例 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文档是否格式良好并产生预期结果,请使用带有--vex-location标志的docker scout cves命令,通过CLI将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文档时,你可以通过以下方式将其附加到你的图像上:
- 将文件作为 attestation附加
- 将文档嵌入到 image filesystem
一旦将VEX文档添加到图像中,您就无法将其移除。对于作为证明附加的文档,您可以创建一个新的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: the location and filename of the VEX document--predicate-type: the in-totopredicateTypefor OpenVEX
图像文件系统
如果您在构建镜像之前就已经知道异常情况,那么将VEX文档直接嵌入到镜像文件系统上是一个不错的选择。而且这相对容易;只需在您的Dockerfile中使用COPY命令将VEX文档复制到镜像中。
这种方法的缺点是您以后无法更改或更新异常。图像层是不可变的,因此您放入图像文件系统中的任何内容都将永久存在。将文档附加为attestation提供了更好的灵活性。
注意
嵌入在镜像文件系统中的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模式。
文件存储在镜像文件系统的哪个位置并不重要。
请注意,复制的文件必须是最终镜像文件系统的一部分, 对于多阶段构建,文档必须在最终阶段保留。