feat(vex): improve relationship support in CSAF VEX (#6735)

Signed-off-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
Teppei Fukuda
2024-05-28 14:51:07 +04:00
committed by GitHub
parent e66dbb9357
commit a447f6ba94
7 changed files with 325 additions and 279 deletions

View File

@@ -11,8 +11,6 @@ Currently, Trivy supports the following three formats:
- [OpenVEX](https://github.com/openvex/spec)
- [CSAF](https://oasis-open.github.io/csaf-documentation/specification.html)
This is still an experimental implementation, with only minimal functionality added.
## CycloneDX
| Target | Supported |
|:---------------:|:---------:|
@@ -40,7 +38,7 @@ The following steps are required:
### Generate the SBOM
You can generate a CycloneDX SBOM with Trivy as follows:
```shell
```bash
$ trivy image --format cyclonedx --output debian11.sbom.cdx debian:11
```
@@ -49,7 +47,7 @@ Next, create a VEX based on the generated SBOM.
Multiple vulnerability statuses can be defined under `vulnerabilities`.
Take a look at the example below.
```
```bash
$ cat <<EOF > trivy.vex.cdx
{
"bomFormat": "CycloneDX",
@@ -105,7 +103,7 @@ For more details on CycloneDX VEX and BOM-Link, please refer to the following li
### Scan SBOM with VEX
Provide the VEX when scanning the CycloneDX SBOM.
```
```bash
$ trivy sbom trivy.sbom.cdx --vex trivy.vex.cdx
...
2023-04-13T12:55:44.838+0300 INFO Filtered out the detected vulnerability {"VEX format": "CycloneDX", "vulnerability-id": "CVE-2020-8911", "status": "not_affected", "justification": "code_not_reachable"}
@@ -145,10 +143,10 @@ The following steps are required:
### Create the VEX document
Please see also [the example](https://github.com/openvex/examples).
In Trivy, [the Package URL (PURL)][purl] is used as the product identifier.
Trivy requires [the Package URL (PURL)][purl] as the product identifier.
```
$ cat <<EOF > debian11.openvex
```bash
$ cat <<EOF > debian11.openvex.json
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "https://openvex.dev/docs/public/vex-2e67563e128250cbcb3e98930df948dd053e43271d70dc50cfa22d57e03fe96f",
@@ -169,19 +167,107 @@ $ cat <<EOF > debian11.openvex
EOF
```
In the above example, PURLs, located in `packages.externalRefs.referenceLocator` in SPDX are used for the product identifier.
In the above example, PURLs, `pkg:deb/debian/libdb5.3@5.3.28+dfsg1-0.8` are used for the product identifier.
You can find PURLs in the JSON report generated by Trivy.
This VEX statement is applied if the PURL specified in the VEX matches the PURL found during the scan.
See [here](#purl-matching) for more details of PURL matching.
!!! note
If a qualifier is specified in the PURL used as the product id in the VEX, the qualifier is compared.
Other qualifiers are ignored in the comparison.
`pkg:deb/debian/curl@7.50.3-1` in OpenVEX matches `pkg:deb/debian/curl@7.50.3-1?arch=i386`,
while `pkg:deb/debian/curl@7.50.3-1?arch=amd64` does not match `pkg:deb/debian/curl@7.50.3-1?arch=i386`.
Trivy also supports [OpenVEX subcomponents][openvex-subcomponent], which allow for more precise specification of the scope of a VEX statement, reducing the risk of incorrect filtering.
Let's say you want to suppress vulnerabilities within a container image.
If you only specify the PURL of the container image as the product, the resulting VEX would look like this:
<details>
<summary>OpenVEX products only</summary>
```json
"statements": [
{
"vulnerability": {"name": "CVE-2024-32002"},
"products": [
{"@id": "pkg:oci/trivy?repository_url=ghcr.io%2Faquasecurity%2Ftrivy"}
],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}
]
```
</details>
However, this approach would suppress all instances of CVE-2024-32002 within the container image.
If the intention is to declare that the `git` package distributed by Alpine Linux within this image is not affected, subcomponents can be utilized as follows:
<details>
<summary>OpenVEX subcomponents</summary>
```json
"statements": [
{
"vulnerability": {"name": "CVE-2024-32002"},
"products": [
{
"@id": "pkg:oci/trivy?repository_url=ghcr.io%2Faquasecurity%2Ftrivy",
"subcomponents": [
{"@id": "pkg:apk/alpine/git"}
]
}
],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}
]
```
</details>
By declaring the subcomponent in this manner, Trivy will filter the results, considering only the `git` package within the `ghcr.io/aquasecurity/trivy` container image as not affected.
Omitting the version in the PURL applies the statement to all versions of the package.
More details about PURL matching can be found [here](#purl-matching).
Furthermore, the product specified in a VEX statement does not necessarily need to be the target of the scan.
It is possible to specify a component that is included in the scan target as the product.
For example, you can designate a specific Go project as the product and its dependent modules as subcomponents.
In the following example, the VEX statement declares that the `github.com/docker/docker` module, which is a dependency of the `github.com/aquasecurity/trivy` Go project, is not affected by CVE-2024-29018.
<details>
<summary>OpenVEX intermediate components</summary>
```json
"statements": [
{
"vulnerability": {"name": "CVE-2024-29018"},
"products": [
{
"@id": "pkg:golang/github.com/aquasecurity/trivy",
"subcomponents": [
{ "@id": "pkg:golang/github.com/docker/docker" }
]
}
],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}
]
```
</details>
This VEX document can be used when scanning a container image as well as other targets.
The VEX statement will be applied when Trivy finds the Go binary within the container image.
```bash
$ trivy image ghcr.io/aquasecurity/trivy:0.50.0 --vex trivy.openvex.json
```
VEX documents can indeed be reused across different container images, eliminating the need to issue separate VEX documents for each image.
This is particularly useful when there is a common component or library that is used across multiple projects or container images.
### Scan with VEX
Provide the VEX when scanning your target.
```
$ trivy image debian:11 --vex debian11.openvex
```bash
$ trivy image debian:11 --vex debian11.openvex.json
...
2023-04-26T17:56:05.358+0300 INFO Filtered out the detected vulnerability {"VEX format": "OpenVEX", "vulnerability-id": "CVE-2019-8457", "status": "not_affected", "justification": "vulnerable_code_not_in_execute_path"}
@@ -215,7 +301,10 @@ The following steps are required:
### Create the CSAF document
Create a CSAF document in JSON format as follows:
```
<details>
<summary>CSAF VEX</summary>
```bash
$ cat <<EOF > debian11.vex.csaf
{
"document": {
@@ -313,10 +402,20 @@ $ cat <<EOF > debian11.vex.csaf
EOF
```
</details>
Trivy also supports [CSAF relationships][csaf-relationship], reducing the risk of incorrect filtering.
It works in the same way as OpenVEX subcomponents.
At present, the specified relationship category is not taken into account and all the following categories are treated internally as "depends_on".
- default_component_of
- installed_on
- installed_with
### Scan with CSAF VEX
Provide the CSAF document when scanning your target.
```console
```bash
$ trivy image debian:11 --vex debian11.vex.csaf
...
2024-01-02T10:28:26.704+0100 INFO Filtered out the detected vulnerability {"VEX format": "CSAF", "vulnerability-id": "CVE-2019-8457", "status": "not_affected"}
@@ -376,3 +475,6 @@ does not match:
[openvex]: https://github.com/openvex/spec
[purl]: https://github.com/package-url/purl-spec
[purl-matching]: https://github.com/openvex/spec/issues/27
[openvex-subcomponent]: https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md#subcomponent
[csaf-relationship]: https://docs.oasis-open.org/csaf/csaf/v2.0/os/csaf-v2.0-os.html#3224-product-tree-property---relationships