Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 3 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 120 additions & 18 deletions docs/docs/supply-chain/vex.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
|:---------------:|:---------:|
Expand Down Expand Up @@ -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
```

Expand All @@ -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",
Expand Down Expand Up @@ -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"}
Expand Down Expand Up @@ -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",
Expand All @@ -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/[email protected]+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/[email protected]` in OpenVEX matches `pkg:deb/debian/[email protected]?arch=i386`,
while `pkg:deb/debian/[email protected]?arch=amd64` does not match `pkg:deb/debian/[email protected]?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"}

Expand Down Expand Up @@ -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": {
Expand Down Expand Up @@ -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"}
Expand Down Expand Up @@ -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
Loading