From 2c891f052a2c866290f7dfc51549ef511f327e6c Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Fri, 6 Sep 2024 15:54:32 +0200 Subject: [PATCH] scout: create exceptions in dashboard Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> --- content/scout/explore/exceptions.md | 349 ++++-------------- content/scout/guides/vex.md | 300 --------------- .../scout/how-tos/create-exceptions-gui.md | 78 ++++ .../scout/how-tos/create-exceptions-vex.md | 318 ++++++++++++++++ content/scout/images/suppressed-cve-cli.png | Bin 0 -> 47812 bytes content/scout/release-notes/platform.md | 2 - data/toc.yaml | 6 +- 7 files changed, 468 insertions(+), 585 deletions(-) delete mode 100644 content/scout/guides/vex.md create mode 100644 content/scout/how-tos/create-exceptions-gui.md create mode 100644 content/scout/how-tos/create-exceptions-vex.md create mode 100644 content/scout/images/suppressed-cve-cli.png diff --git a/content/scout/explore/exceptions.md b/content/scout/explore/exceptions.md index 2493460165..adbb2a3711 100644 --- a/content/scout/explore/exceptions.md +++ b/content/scout/explore/exceptions.md @@ -9,9 +9,8 @@ keywords: scout, cves, suppress, vex, exceptions Vulnerabilities found in container images sometimes need additional context. Just because an image contains a vulnerable package, it doesn't mean that the -vulnerability is exploitable. **Exceptions** in Docker Scout lets you address -false positives in image analysis using Vulnerability Exploitability -eXchange (VEX) documents. +vulnerability is exploitable. **Exceptions** in Docker Scout lets you +acknowledge accepted risks or address false positives in image analysis. By negating non-applicable vulnerabilities, you can make it easier for yourself and downstream consumers of your images to understand the security implications @@ -21,296 +20,84 @@ In Docker Scout, exceptions are automatically factored into the results. If an image contains an exception that flags a CVE as non-applicable, then that CVE is excluded from analysis results. -## Create an exception +## Create exceptions -To add an exception to an image, you need a VEX document. VEX is a standard -format for documenting vulnerabilities in the context of a software package or -product. +To create an exception for an image, you can: -There are multiple implementations and formats of VEX. Docker Scout supports -the [OpenVex](https://github.com/openvex/spec) implementation. To create an -OpenVEX document, use the [`vexctl`](https://github.com/openvex/vexctl) command -line tool. +- Create an exception in the [GUI](/scout/how-tos/create-exceptions-gui.md) of + Docker Scout Dashboard. -The following example command creates a VEX document stating that: +- Create a [VEX](/scout/how-tos/create-exceptions-vex.md) document and attach + it to the image. -- The software product described by this VEX document is the Docker image - `example/app:v1` -- The image contains the npm package `express@4.17.1` -- The npm package is affected by a known vulnerability: `CVE-2022-24999` -- The image is unaffected by the CVE, because the vulnerable code is never - executed in containers that run this image - -```console -$ 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" -``` - -Here's a description of the options in this example: - -`--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 - [specification](https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#docker). - - Docker image PURL strings begin with a `pkg:docker` type prefix, followed by - the image repository and version (the image tag or SHA256 digest). Unlike - image tags, where the version is specified like `example/app:v1`, in PURL the - image repository and version are separated by an `@`. - -`--subcomponents` -: PURL of the vulnerable package in the image. In this example, the - vulnerability exists in an npm package, so the `--subcomponents` PURL is the - identifier for the npm package name and version (`pkg:npm/express@4.17.1`). - - If the same vulnerability exists in multiple packages, `vexctl` lets you - specify the `--subcomponents` flag multiple times for a single `create` - command. - - You can also omit `--subcomponents`, in which case the VEX statement applies - to the entire image. - -`--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_affected` - - `affected` - - `fixed` - - `under_investigation` - - In this example, the VEX statement asserts that the Docker image is - `not_affected` by the vulnerability. The `not_affected` status is the only - status that results in CVE suppression, where the CVE is filtered out of the - analysis results. The other statuses are useful for documentation purposes, - but they do not work for creating exceptions. For more information about all - the possible status labels, see [Status Labels](https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md#status-labels) - in the OpenVEX specification. - -`--justification` -: Justifies the `not_affected` status label, informing why the product is not - affected by the vulnerability. In this case, the justification given is - `vulnerable_code_not_in_execute_path`, signalling that the vulnerability - can't be executed as used by the product. - - In OpenVEX, status justifications can have one of the five possible values: - - - `component_not_present` - - `vulnerable_code_not_present` - - `vulnerable_code_not_in_execute_path` - - `vulnerable_code_cannot_be_controlled_by_adversary` - - `inline_mitigations_already_exist` - - For more information about these values and their definitions, see - [Status Justifications](https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md#status-justifications) - in the OpenVEX specification. - -`--file` -: Filename of the VEX document output - -Here's the OpenVEX JSON generated by this command: - -```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" - } - ] -} -``` - -Understanding how VEX documents are supposed to be structured can be a bit of a -mouthful. The [OpenVEX specification](https://github.com/openvex/spec) -describes the format and all the possible properties of documents and -statements. For the full details, refer to the specification to learn more -about the available fields and how to create a well-formed OpenVEX document. - -To learn more about the available flags and syntax of the `vexctl` CLI tool and -how to install it, refer to the [`vexctl` GitHub repository](https://github.com/openvex/vexctl). - -For an introduction to VEX, you may also want to check out this use-case guide: -[Suppress image vulnerabilities with VEX](/scout/guides/vex.md). - -## Verifying VEX documents - -To test whether the VEX documents you create are well-formed and produce the -expected results, use the `docker scout cves` command with the `--vex-location` -flag to apply a VEX document to a local image analysis using the CLI. - -The following command invokes a local image analysis that incorporates all VEX -documents in the specified location, using the `--vex-location` flag. In this -example, the CLI is instructed to look for VEX documents in the current working -directory. - -```console -$ docker scout cves --vex-location . -``` - -The output of the `docker scout cves` command displays the results with any VEX -statements found in under the `--vex-location` location factored into the -results. For example, CVEs assigned a status of `not_affected` are filtered out -from the results. If the output doesn't seem to take the VEX statements into -account, that's an indication that the VEX documents might be invalid in some -way. - -Things to look out for include: - -- The PURL of a Docker image must begin with `pkg:docker/` followed by the image name. -- In a Docker image PURL, the image name and version is separated by `@`. - An image named `example/myapp:1.0` has the following PURL: `pkg:docker/example/myapp@1.0`. -- Remember to specify an `author` (it's a mandatory field in OpenVEX) -- The [OpenVEX specification](https://github.com/openvex/spec) describes how - and when to use `justification`, `impact_statement`, and other fields in the - VEX documents. Specifying these in an incorrect way results in an invalid - document. Make sure your VEX documents comply with the OpenVEX specification. - -## Attach exceptions to images - -When you've created an exception, -you can attach it to your image in the following ways: - -- Attach the document as an [attestation](#attestation) -- Embed the document in the [image filesystem](#image-filesystem) - -You can't remove a VEX document from an image once it's been added. For -documents attached as attestations, you can create a new VEX document and -attach it to the image again. Doing so will overwrite the previous VEX document -(but it won't remove the attestation). For images where the VEX document has -been embedded in the image's filesystem, you need to rebuild the image to -change the VEX document. - -### Attestation - -To attach exceptions as an attestation, you can use the `docker scout -attestation add` CLI command. Using attestations is the recommended option for attaching exceptions to -images. - -You can attach attestations to images that have already been pushed to a -registry. You don't need to build or push the image again. Additionally, having -the exceptions attached to the image as attestations means consumers can -inspect the exceptions for an image, directly from the registry. - -To attach an attestation to an image: - -1. Build the image and push it to a registry. - - ```console - $ docker build --provenance=true --sbom=true --tag --push . - ``` - -2. Attach the exception to the image as an attestation. - - ```console - $ docker scout attestation add \ - --file .vex.json \ - --predicate-type https://openvex.dev/ns/v0.2.0 \ - - ``` - - The options for this command are: - - - `--file`: the location and filename of the VEX document - - `--predicate-type`: the in-toto `predicateType` for OpenVEX - -### Image filesystem - -Embedding exceptions directly on the image filesystem is a good option if you -know the exceptions ahead of time, before you build the image. And it's easy; -just `COPY` the VEX document to the image in your Dockerfile. - -The downside with this approach is that you can't change or update the -exception later. Image layers are immutable, so anything you put in the image's -filesystem is there forever. Attaching the document as an -[attestation](#attestation) provides better flexibility. - -> [!NOTE] -> -> VEX documents embedded in the image filesystem are not considered for images -> that have attestations. If your image has **any** attestations, Docker Scout -> will only look for exceptions in the attestations, and not in the image -> filesystem. -> -> If you want to use the VEX document embedded in the image filesystem, you -> must remove the attestation from the image. Note that provenance attestations -> may be added automatically for images. To ensure that no attestations are -> added to the image, you can explicitly disable both SBOM and provenance -> attestations using the `--provenance=false` and `--sbom=false` flags when -> building the image. - -To embed a VEX document on the image filesystem, `COPY` the file into the image -as part of the image build. The following example shows how to copy all VEX -documents under `.vex/` in the build context, to `/var/lib/db` in the image. - -```dockerfile -# syntax=docker/dockerfile:1 - -FROM alpine -COPY .vex/* /var/lib/db/ -``` - -The filename of the VEX document must match the `*.vex.json` glob pattern. -It doesn't matter where on the image's filesystem you store the file. - -Note that the copied files must be part of the filesystem of the final image, -For multi-stage builds, the documents must persist in the final stage. +The recommended way to create exceptions is to use Docker Scout Dashboard. The +GUI provides a user-friendly interface for creating exceptions. It also lets +you create exceptions for multiple images, or your entire organization, all at +once. ## View exceptions -The **Exceptions** page on the [Docker Scout Dashboard](https://scout.docker.com/) -lists the exceptions for all images in your organization. Selecting a row in -the list opens the exception side panel, which displays more information about -the exception and where it comes from. +To view exceptions for images, you need to have the appropriate permissions. + +- Exceptions created [using the GUI](/scout/how-tos/create-exceptions-gui.md) + are visible to members of your Docker organization. Unauthenticated users or + users who aren't members of your organization cannot see these exceptions. +- Exceptions created [using VEX documents](/scout/how-tos/create-exceptions-vex.md) + are visible to anyone who can pull the image, since the VEX document is + stored in the image manifest or on filesystem of the image. + +### View exceptions in Docker Scout Dashboard + +The [**Exceptions** tab](https://scout.docker.com/reports/vulnerabilities/exceptions) +of the Vulnerabilities page in Docker Scout Dashboard lists all exceptions for +for all images in your organization. From here, you can see more details about +each exception, the CVEs being suppressed, the images that exceptions apply to, +the type of exception and how it was created, and more. + +For exceptions created using the [GUI](/scout/how-tos/create-exceptions-gui.md), +selecting the action menu lets you edit or remove the exception. To view all exceptions for a specific image tag: -{{< tabs >}} -{{< tab name="Docker Scout Dashboard" >}} - 1. Go to the [Images page](https://scout.docker.com/reports/images). 2. Select the tag that you want to inspect. -3. Open the **Image attestations** tab. +3. Open the **Exceptions** tab. -{{< /tab >}} -{{< tab name="Docker Desktop" >}} +### View exceptions in the CLI -1. Open the **Images** view in Docker Desktop. -2. Open the **Hub** tab. -3. Select the tag you want to inspect. -4. Open the **Image attestations** tab. +{{% experimental %}} +Viewing exceptions in the CLI is an experimental feature. +It requires the latest version of the Docker Scout CLI plugin. +Some exceptions may not appear correctly in the CLI. +{{% /experimental %}} -{{< /tab >}} -{{< /tabs >}} +Vulnerability exceptions are highlighted in the CLI when you run `docker scout +cves `. If a CVE is suppressed by an exception, a `SUPPRESSED` label +appears next to the CVE ID. Details about the exception are also displayed. + +![SUPPRESSED label in the CLI output](/scout/images/suppressed-cve-cli.png) + +> [!IMPORTANT] +> In order to view exceptions in the CLI, you must configure the CLI to use +> the same Docker organization that you used to create the exceptions. +> +> To configure an organization for the CLI, run: +> +> ```console +> $ docker scout configure organization +> ``` +> +> Replace `` with the name of your Docker organization. +> +> You can also set the organization on a per-command basis by using the +> `--org` flag: +> +> ```console +> $ docker scout cves --org +> ``` + +To exclude suppressed CVEs from the output, use the `--ignore-suppressed` flag: + +```console +$ docker scout cves --ignore-suppressed +``` diff --git a/content/scout/guides/vex.md b/content/scout/guides/vex.md deleted file mode 100644 index b72a29045b..0000000000 --- a/content/scout/guides/vex.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: Suppress image vulnerabilities with VEX -description: An introduction to using VEX with Docker Scout -keywords: scout, vex, Vulnerability Exploitability eXchange, openvex, vulnerabilities, cves ---- - -Vulnerability Exploitability eXchange (VEX) is a way to add context -about how a software product is affected by a vulnerable component. -In this guide, you will learn about: - -- How VEX can help you suppress non-applicable or fixed vulnerabilities found in your images -- How to create VEX documents and statements -- How to apply and consume VEX data with Docker Scout - -> **Experimental** -> -> Support for VEX is an experimental feature in Docker Scout. -> We recommend that you do not use this feature in production environments -> as this feature may change or be removed from future releases. -{ .experimental } - -## Prerequisites - -If you want to follow along the steps of this guide, you'll need the following: - -- The latest version of Docker Desktop -- The [containerd image store](../../desktop/containerd.md) must be enabled -- Git -- A [Docker account](/accounts/create-account/) -- A GitHub account - -## Introduction to VEX - -Just because a software product contains a vulnerable component, -it doesn't mean that the vulnerability is exploitable. -For example, the vulnerable component might never be -loaded into memory when the application runs. -Or the vulnerability might have been fixed, -but the system that detects the vulnerability is unaware. - -The concept of VEX is defined by a working group by -the United States Cybersecurity and Infrastructure Security Agency (CISA). -At the core of VEX are exploitability assessments. -These assessments describe the status of a given CVE for a product. -The possible vulnerability statuses in VEX are: - -- Not affected: No remediation is required regarding this vulnerability. -- Affected: Actions are recommended to remediate or address this vulnerability. -- Fixed: These product versions contain a fix for the vulnerability. -- Under investigation: It is not yet known whether these product versions are affected by the vulnerability. An update will be provided in a later release. - -There are multiple implementations of VEX, -and the exact format and properties of a VEX document differ -depending on the implementation of VEX that you use. -Examples of VEX implementations include: - -- OpenVEX -- Open Security Advisory Framework (OSAF) -- CycloneDX -- SPDX - -This guide uses the OpenVEX implementation in its examples. -For more information about OpenVEX, -refer to the [specification](https://github.com/openvex/spec). - -In all implementations, the core idea is the same: -to provide a framework for describing the impact of vulnerabilities. -Key components of VEX regardless of implementation includes: - -VEX document -: A type of security advisory for storing VEX statements. - The format of the document depends on the specific implementation. - -VEX statement -: Describes the status of a vulnerability in a product, - whether it's exploitable, and whether there are ways to remediate the issue. - -Justification and impact -: Depending on the vulnerability status, statements include a justification - or impact statement describing why a product is or isn't affected. - -Action statements -: Describe how to remediate or mitigate the vulnerability. - -This added context that VEX provides around vulnerabilities -helps organizations perform risk assessment of software products. - -## Create and enable a repository - -To get started, create a sample project to work with. -Use the [Docker Scout demo service](https://github.com/docker/scout-demo-service) -template repository to bootstrap a new repository in your own GitHub organization. - -1. Create the repository from the template. -2. Clone the Git repository to your machine. -3. Build an image from the repository and push it to a new Docker Hub repository. - - ```console - $ cd scout-demo-service - $ docker build --provenance=true --sbom=true --tag /scout-demo-service:v1 --push . - ``` - -4. Enable Docker Scout on the repository. - - ```console - $ docker scout repo enable /scout-demo-service - ``` - -## Inspect vulnerability - -Use the `docker scout cves` command to view the vulnerabilities for the image. -For the purpose of this guide, we'll concentrate on a particular CVE: CVE-2022-24999. - -```console -$ docker scout cves --only-cve-id CVE-2022-24999 -``` - -The output from this command shows that this CVE affects two JavaScript packages -in the image: `express@4.17.1` and `qs@6.7.0`. - -Now, let's imagine that you've reviewed this vulnerability -and determined that the exploit doesn't affect your application -because the vulnerable code is never executed. -Your image would still show as containing a `HIGH` severity vulnerability, -merely by having the component in the SBOM. - -This is a situation where VEX can help suppress the CVE for your product. - -## Create a VEX document - -OpenVEX, the implementation of VEX used in this guide, -provides a CLI tool for generating VEX documents called `vexctl`. -If you have Go installed on your system, -you can install `vexctl` using the `go install` command: - -```console -$ go install github.com/openvex/vexctl@latest -``` - -Otherwise, you can grab a prebuilt binary from the `vexctl` -[releases page](https://github.com/openvex/vexctl/releases) on GitHub. - -Use the `vexctl create` command to create an OpenVEX document. -The following command creates a VEX document `CVE-2022-24999.vex.json` -which states that the Docker image and its sub-components -are unaffected by the CVE because the vulnerable code is never executed. - -```console -$ vexctl create \ - --author="author@example.com" \ - --product="pkg:docker//scout-demo-service@v1" \ - --subcomponents="pkg:npm/express@4.17.1" \ - --subcomponents="pkg:npm/qs@6.7.0" \ - --vuln="CVE-2022-24999" \ - --status="not_affected" \ - --justification="vulnerable_code_not_in_execute_path" \ - --file="CVE-2022-24999.vex.json" -``` - -This creates a VEX document that looks like this: - -```json -{ - "@context": "https://openvex.dev/ns/v0.2.0", - "@id": "https://openvex.dev/docs/public/vex-a7e7c69be57bc49dec9cc2f3a3e3329b12674ca53b53a53ab42134dcc0510779", - "author": "author@example.com", - "timestamp": "2024-02-03T09:33:28.913572+01:00", - "version": 1, - "statements": [ - { - "vulnerability": { - "name": "CVE-2022-24999" - }, - "timestamp": "2024-02-03T09:33:28.913574+01:00", - "products": [ - { - "@id": "pkg:docker//scout-demo-service@v1", - "subcomponents": [ - { - "@id": "pkg:npm/express@4.17.1" - }, - { - "@id": "pkg:npm/qs@6.7.0" - } - ] - } - ], - "status": "not_affected", - "justification": "vulnerable_code_not_in_execute_path" - } - ] -} -``` - -## Verify CVE suppression - -To test whether the VEX statement provides the expected security advisory, -use the `docker scout cves` command to review the CVE status. -The `--vex-location` flag lets you specify a directory containing VEX documents. - -```console -$ docker scout cves --only-cve-id CVE-2022-24999 --vex-location . -``` - -You should now see `VEX` fields appear in the output of the command. - -```text {hl_lines=[7,8]} -✗ HIGH CVE-2022-24999 [OWASP Top Ten 2017 Category A9 - Using Components with Known Vulnerabilities] - https://scout.docker.com/v/CVE-2022-24999 - Affected range : <4.17.3 - Fixed version : 4.17.3 - CVSS Score : 7.5 - CVSS Vector : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - VEX : not affected [vulnerable code not in execute path] - : author@example.com -``` - -## Attach VEX documents to images - -To distribute VEX statements together with your images, -you can embed the VEX document in an in-toto attestation. -This is also how BuildKit attaches SBOM and provenance attestations to images. - -When you encapsulate a VEX document in an in-toto attestation, -the OpenVEX specification recommends a different format for the VEX document. -In-toto attestations already contain the image reference in the attestation predicate, -making the image reference in the `products` key of the VEX document redundant. -Instead, `products` should refer to the packages that contain the vulnerabilities -(`subcomponents` in the VEX document shown earlier). - -1. Create a new `in-toto.vex.json` document with the following contents: - - ```json - { - "@context": "https://openvex.dev/ns/v0.2.0", - "@id": "https://openvex.dev/docs/public/vex-a7e7c69be57bc49dec9cc2f3a3e3329b12674ca53b53a53ab42134dcc0510779", - "author": "author@example.com", - "timestamp": "2024-02-03T09:33:28.913572+01:00", - "version": 1, - "statements": [ - { - "vulnerability": { - "name": "CVE-2022-24999" - }, - "timestamp": "2024-02-03T09:33:28.913574+01:00", - "products": [ - { - "@id": "pkg:npm/express@4.17.1" - }, - { - "@id": "pkg:npm/qs@6.7.0" - } - ], - "status": "not_affected", - "justification": "vulnerable_code_not_in_execute_path" - } - ] - } - ``` - -2. Attach the `in-toto.vex.json` VEX document as an attestation: - - ```console - $ docker scout attestation add \ - --file in-toto.vex.json \ - --predicate-type https://openvex.dev/ns/v0.2.0 \ - /scout-demo-service:v1 - ``` - - This adds an in-toto attestation to the image, - with a predicate type of `https://openvex.dev/ns/v0.2.0`. - -3. Analyze the image with `docker scout cves`. - - > [!NOTE] - > - > This only works when analyzing remote images in a registry. - > To force Docker Scout to analyze a registry image instead of a local one, - > specify the image reference with a `registry://` prefix. - - ```console - $ docker scout cves \ - --only-cve-id CVE-2022-24999 \ - registry:///scout-demo-service:v1 - ``` - -## Summary - -In this guide, you've learned about: - -- How VEX is a concept that can help you optimize vulnerability triaging -- How to create VEX documents and use them in image analysis -- How you can distribute VEX with your images as in-toto attestations - -For more information about VEX: - -- [VEX Status Justifications (CISA)](https://www.cisa.gov/sites/default/files/publications/VEX_Status_Justification_Jun22.pdf) -- [VEX Use Cases (CISA)](https://www.cisa.gov/sites/default/files/publications/VEX_Use_Cases_Document_508c.pdf) -- [OpenVEX specification](https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md) -- [Manage vulnerability exceptions](/scout/explore/exceptions.md) diff --git a/content/scout/how-tos/create-exceptions-gui.md b/content/scout/how-tos/create-exceptions-gui.md new file mode 100644 index 0000000000..fae5197b42 --- /dev/null +++ b/content/scout/how-tos/create-exceptions-gui.md @@ -0,0 +1,78 @@ +--- +title: Create an exception using the GUI +description: Create an exception for a vulnerability in an image using the Docker Scout Dashboard. +keywords: Docker, Docker Scout, vulnerability, exception, create, GUI +--- + +The Docker Scout Dashboard provides a user-friendly interface for creating +[exceptions](/scout/explore/exceptions.md) for vulnerabilities found in +container images. Exceptions let you acknowledge accepted risks or address +false positives in image analysis. + +## Prerequisites + +To create an in the Docker Scout Dashboard, you need a Docker account with +**Editor** or **Owner** permissions for the Docker organization that owns the +image. + +## Steps + +To create an exception for a vulnerability in an image using the Docker Scout +Dashboard: + +1. Go to the [Images page](https://scout.docker.com/reports/images). +2. Select the image tag that contains the vulnerability you want to create an + exception for. +3. Open the **Image layers** tab. +4. Select the layer that contains the vulnerability you want to create an + exception for. +5. In the **Vulnerabilities** tab, find the vulnerability you want to create an + exception for. Vulnerabilities are grouped by package. Find the package that + contains the vulnerability you want to create an exception for, and then + expand the package. +6. Select the **Create exception** button next to the vulnerability. + +{{% create_panel.inline %}} +Selecting the **Create exception** button opens the **Create exception** side panel. +In this panel, you can provide the details of the exception: + +- **Exception type**: The type of exception. The only supported types are: + + - **Accepted risk**: The vulnerability is not addressed due to its minimal + security risk, high remediation costs, dependence on an upstream fix, or + similar. + - **False positive**: The vulnerability presents no security risk in your + specific use case, configuration, or because of measures in place that + block exploitation + + If you select **False positive**, you must provide a justification for why + the vulnerability is a false positive: + +- **Additional details**: Any additional information that you want to + provide about the exception. + +- **Scope**: The scope of the exception. The scope can be: + + - **Image**: The exception applies to the selected image. + - **All images in repository**: The exception applies to all images in the + repository. + - **Specific repository**: The exception applies to all images in the + specified repositories. + - **All images in my organization**: The exception applies to all images in + your organization. + +- **Package scope**: The scope of the exception. The package scope can be: + + - **Selected package**: The exception applies to the selected package. + - **Any packages**: The exception applies to all packages vulnerable to this + CVE. + +When you've filled in the details, select the **Create** button to create the +exception. + +The exception is now created and factored into the analysis results for the +images that you selected. The exception is also listed on the **Exceptions** +tab of the [Vulnerabilities page](https://scout.docker.com/reports/vulnerabilities/exceptions) +in the Docker Scout Dashboard. + +{{% /create_panel.inline %}} diff --git a/content/scout/how-tos/create-exceptions-vex.md b/content/scout/how-tos/create-exceptions-vex.md new file mode 100644 index 0000000000..ca645aad82 --- /dev/null +++ b/content/scout/how-tos/create-exceptions-vex.md @@ -0,0 +1,318 @@ +--- +title: Create an exception using the VEX +description: Create an exception for a vulnerability in an image using VEX documents. +keywords: Docker, vulnerability, exception, create, VEX +aliases: + - /scout/guides/vex/ +--- + +Vulnerability Exploitability eXchange (VEX) is a standard format for +documenting vulnerabilities in the context of a software package or product. +Docker Scout supports VEX documents to create +[exceptions](/scout/explore/exceptions.md) for vulnerabilities in images. + +> [!NOTE] +> You can also create exceptions using the Docker Scout Dashboard or Docker +> Desktop. The GUI provides a user-friendly interface for creating exceptions, +> and it's easy to manage exceptions for multiple images. It also lets you +> create exceptions for multiple images, or your entire organization, all at +> once. For more information, see [Create an exception using the GUI](/scout/how-tos/create-exceptions-gui.md). + +## Prerequisites + +To create exceptions using OpenVEX documents, you need: + +- The latest version of Docker Desktop or the Docker Scout CLI plugin +- The [`vexctl`](https://github.com/openvex/vexctl) command line tool. +- The [containerd image store](../../desktop/containerd.md) must be enabled +- Write permissions to the registry repository where the image is stored + +## Introduction to VEX + +The VEX standard is defined by a working group by the United States +Cybersecurity and Infrastructure Security Agency (CISA). At the core of VEX are +exploitability assessments. These assessments describe the status of a given +CVE for a product. The possible vulnerability statuses in VEX are: + +- Not affected: No remediation is required regarding this vulnerability. +- Affected: Actions are recommended to remediate or address this vulnerability. +- Fixed: These product versions contain a fix for the vulnerability. +- Under investigation: It is not yet known whether these product versions are affected by the vulnerability. An update will be provided in a later release. + +There are multiple implementations and formats of VEX. Docker Scout supports +the [OpenVex](https://github.com/openvex/spec) implementation. Regardless of +the specific implementation, the core idea is the same: to provide a framework +for describing the impact of vulnerabilities. Key components of VEX regardless +of implementation includes: + +VEX document +: A type of security advisory for storing VEX statements. + The format of the document depends on the specific implementation. + +VEX statement +: Describes the status of a vulnerability in a product, + whether it's exploitable, and whether there are ways to remediate the issue. + +Justification and impact +: Depending on the vulnerability status, statements include a justification + or impact statement describing why a product is or isn't affected. + +Action statements +: Describe how to remediate or mitigate the vulnerability. + +## `vexctl` example + +The following example command creates a VEX document stating that: + +- The software product described by this VEX document is the Docker image + `example/app:v1` +- The image contains the npm package `express@4.17.1` +- The npm package is affected by a known vulnerability: `CVE-2022-24999` +- The image is unaffected by the CVE, because the vulnerable code is never + executed in containers that run this image + +```console +$ 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" +``` + +Here's a description of the options in this example: + +`--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 + [specification](https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#docker). + + Docker image PURL strings begin with a `pkg:docker` type prefix, followed by + the image repository and version (the image tag or SHA256 digest). Unlike + image tags, where the version is specified like `example/app:v1`, in PURL the + image repository and version are separated by an `@`. + +`--subcomponents` +: PURL of the vulnerable package in the image. In this example, the + vulnerability exists in an npm package, so the `--subcomponents` PURL is the + identifier for the npm package name and version (`pkg:npm/express@4.17.1`). + + If the same vulnerability exists in multiple packages, `vexctl` lets you + specify the `--subcomponents` flag multiple times for a single `create` + command. + + You can also omit `--subcomponents`, in which case the VEX statement applies + to the entire image. + +`--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_affected` + - `affected` + - `fixed` + - `under_investigation` + + In this example, the VEX statement asserts that the Docker image is + `not_affected` by the vulnerability. The `not_affected` status is the only + status that results in CVE suppression, where the CVE is filtered out of the + analysis results. The other statuses are useful for documentation purposes, + but they do not work for creating exceptions. For more information about all + the possible status labels, see [Status Labels](https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md#status-labels) + in the OpenVEX specification. + +`--justification` +: Justifies the `not_affected` status label, informing why the product is not + affected by the vulnerability. In this case, the justification given is + `vulnerable_code_not_in_execute_path`, signalling that the vulnerability + can't be executed as used by the product. + + In OpenVEX, status justifications can have one of the five possible values: + + - `component_not_present` + - `vulnerable_code_not_present` + - `vulnerable_code_not_in_execute_path` + - `vulnerable_code_cannot_be_controlled_by_adversary` + - `inline_mitigations_already_exist` + + For more information about these values and their definitions, see + [Status Justifications](https://github.com/openvex/spec/blob/main/OPENVEX-SPEC.md#status-justifications) + in the OpenVEX specification. + +`--file` +: Filename of the VEX document output + +## Example JSON document + +Here's the OpenVEX JSON generated by this command: + +```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" + } + ] +} +``` + +Understanding how VEX documents are supposed to be structured can be a bit of a +mouthful. The [OpenVEX specification](https://github.com/openvex/spec) +describes the format and all the possible properties of documents and +statements. For the full details, refer to the specification to learn more +about the available fields and how to create a well-formed OpenVEX document. + +To learn more about the available flags and syntax of the `vexctl` CLI tool and +how to install it, refer to the [`vexctl` GitHub repository](https://github.com/openvex/vexctl). + +## Verifying VEX documents + +To test whether the VEX documents you create are well-formed and produce the +expected results, use the `docker scout cves` command with the `--vex-location` +flag to apply a VEX document to a local image analysis using the CLI. + +The following command invokes a local image analysis that incorporates all VEX +documents in the specified location, using the `--vex-location` flag. In this +example, the CLI is instructed to look for VEX documents in the current working +directory. + +```console +$ docker scout cves --vex-location . +``` + +The output of the `docker scout cves` command displays the results with any VEX +statements found in under the `--vex-location` location factored into the +results. For example, CVEs assigned a status of `not_affected` are filtered out +from the results. If the output doesn't seem to take the VEX statements into +account, that's an indication that the VEX documents might be invalid in some +way. + +Things to look out for include: + +- The PURL of a Docker image must begin with `pkg:docker/` followed by the image name. +- In a Docker image PURL, the image name and version is separated by `@`. + An image named `example/myapp:1.0` has the following PURL: `pkg:docker/example/myapp@1.0`. +- Remember to specify an `author` (it's a mandatory field in OpenVEX) +- The [OpenVEX specification](https://github.com/openvex/spec) describes how + and when to use `justification`, `impact_statement`, and other fields in the + VEX documents. Specifying these in an incorrect way results in an invalid + document. Make sure your VEX documents comply with the OpenVEX specification. + +## Attach VEX documents to images + +When you've created a VEX document, +you can attach it to your image in the following ways: + +- Attach the document as an [attestation](#attestation) +- Embed the document in the [image filesystem](#image-filesystem) + +You can't remove a VEX document from an image once it's been added. For +documents attached as attestations, you can create a new VEX document and +attach it to the image again. Doing so will overwrite the previous VEX document +(but it won't remove the attestation). For images where the VEX document has +been embedded in the image's filesystem, you need to rebuild the image to +change the VEX document. + +### Attestation + +To attach VEX documents as an attestation, you can use the `docker scout +attestation add` CLI command. Using attestations is the recommended option for +attaching exceptions to images when using VEX. + +You can attach attestations to images that have already been pushed to a +registry. You don't need to build or push the image again. Additionally, having +the exceptions attached to the image as attestations means consumers can +inspect the exceptions for an image, directly from the registry. + +To attach an attestation to an image: + +1. Build the image and push it to a registry. + + ```console + $ docker build --provenance=true --sbom=true --tag --push . + ``` + +2. Attach the exception to the image as an attestation. + + ```console + $ docker scout attestation add \ + --file .vex.json \ + --predicate-type https://openvex.dev/ns/v0.2.0 \ + + ``` + + The options for this command are: + + - `--file`: the location and filename of the VEX document + - `--predicate-type`: the in-toto `predicateType` for OpenVEX + +### Image filesystem + +Embedding VEX documents directly on the image filesystem is a good option if +you know the exceptions ahead of time, before you build the image. And it's +relatively easy; just `COPY` the VEX document to the image in your Dockerfile. + +The downside with this approach is that you can't change or update the +exception later. Image layers are immutable, so anything you put in the image's +filesystem is there forever. Attaching the document as an +[attestation](#attestation) provides better flexibility. + +> [!NOTE] +> VEX documents embedded in the image filesystem are not considered for images +> that have attestations. If your image has **any** attestations, Docker Scout +> will only look for exceptions in the attestations, and not in the image +> filesystem. +> +> If you want to use the VEX document embedded in the image filesystem, you +> must remove the attestation from the image. Note that provenance attestations +> may be added automatically for images. To ensure that no attestations are +> added to the image, you can explicitly disable both SBOM and provenance +> attestations using the `--provenance=false` and `--sbom=false` flags when +> building the image. + +To embed a VEX document on the image filesystem, `COPY` the file into the image +as part of the image build. The following example shows how to copy all VEX +documents under `.vex/` in the build context, to `/var/lib/db` in the image. + +```dockerfile +# syntax=docker/dockerfile:1 + +FROM alpine +COPY .vex/* /var/lib/db/ +``` + +The filename of the VEX document must match the `*.vex.json` glob pattern. +It doesn't matter where on the image's filesystem you store the file. + +Note that the copied files must be part of the filesystem of the final image, +For multi-stage builds, the documents must persist in the final stage. + diff --git a/content/scout/images/suppressed-cve-cli.png b/content/scout/images/suppressed-cve-cli.png new file mode 100644 index 0000000000000000000000000000000000000000..6384eb66a9e82cdcab9365cab3b5785d64578f2e GIT binary patch literal 47812 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