This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Base and Parent Images

A Docker or OCI image is composed of layers. Some of the layers are created during a build process such as following instructions in a Dockerfile. But many of the layers will come from previously built images. These images likely come from a container team at your organization, or maybe build directly on images from a Linux distribution vendor. In some cases this chain could be many images deep as various teams add standard software or configuration.

Docker uses the FROM clause to denote an image to use as a basis for building a new image. The image provided in this clause is known by Docker as the “Parent Image”, but is commonly referred to as the “Base Image”. This chain of images built from other images using the FROM clause is known as an Image’s ancestry.

Note Docker defines “Base Image” as an image with a FROM SCRATCH clause. Anchore does NOT follow this definition, instead following the more common usage where “Base Image” refers to the image that a given image was built from.

The following is an example of an image with multiple ancestors

A base distro image, for example debian:10

FROM scratch
...

A framework container image from that debian image, for example a node.js image let’s call mynode:latest

FROM debian:10

# Install nodejs

The application image itself built from the framework container, let’s call it myapp:v1

FROM mynode:latest
COPY ./app /
...

In this case, the parent image of myapp:v1 is mynode:latest, while the parent of mynode:latest is debian:10.

Anchore automatically calculates an image’s ancestry as images are scanned. This works by comparing the layer digests of each image to calculate the entire chain of images that produced a given image. The entire ancestry can be retrieved for an image through the GET /v2/images/{image_digest}/ancestors API. See the API docs for more information on the specifics

Some APIs in Anchore accept a base_digest parameter that is used to provide comparison data between two images. These APIs can be used in conjunction with the ancestry API to perform comparisons to the base image so that application developers can focus on results in their direct control.

Some places in Anchore must automatically calculate the comparison image, in these cases the closest ancestor, (the one with the most number of common layers) will be used.

Comparing an Image with its Base or Parent

Anchore Enterprise provides a mechanism to compare the policy checks and security vulnerabilities of an image with those of a base image. This allows clients to

  • filter out results that are inherited from a base image and focus on the results relevant to the application image
  • reverse the focus and examine the base image for policy check violations and vulnerabilities which could be a deciding factor in choosing the base image for the application

To read more about the base comparison features, jump to

1 - Compare Base Image Policy Checks

This feature provides a mechanism to compare the policy checks for an image with those of a base image. You can read more about base images and how to find them here. Base comparison uses the same policy and tag to evaluate both images to ensure a fair comparison. The API yields a response similar to the policy checks API with an additional element within each triggered gate check to indicate whether the result is inherited from the base image.

Usage

This functionality is currently available via the Enterprise UI and API.

API

Refer to API Access section for the API specification. The policy check API (GET /v2/images/{imageDigest}/check) has an optional base_digest query parameter that can be used to specify an image to compare policy findings to. When this query parameter is provided each of the finding’s inherited_from_base field will be filled in with true or false to denote if the finding is present in the provided image. If no image is provided than the inherited_from_base field will be null to indicate no comparison was performed.

Example request using curl to retrieve policy check for an image digest sha256:xyz and tag p/q:r and compare the results to a base image digest sha256:abc

curl -X GET -u {username:password} "http://{servername:port}/v2/images/sha256:xyz/check?tag=p/q:r&base_digest=sha256:abc"

Example output:

{
    "image_digest": "sha256:xyz",
    "evaluated_tag": "p/q:r",
    "evaluations": [
        {
            "comparison_image_digest": "sha256:abc",
            "details": {
                "findings": [
                    {
                        "trigger_id": "41cb7cdf04850e33a11f80c42bf660b3",
                        "gate": "dockerfile",
                        "trigger": "instruction",
                        "message": "Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check",
                        "action": "warn",
                        "policy_id": "48e6f7d6-1765-11e8-b5f9-8b6f228548b6",
                        "recommendation": "",
                        "rule_id": "312d9e41-1c05-4e2f-ad89-b7d34b0855bb",
                        "allowlisted": false,
                        "allowlist_match": null,
                        "inherited_from_base": true
                    },
                    {
                        "trigger_id": "CVE-2019-5435+curl",
                        "gate": "vulnerabilities",
                        "trigger": "package",
                        "message": "MEDIUM Vulnerability found in os package type (APKG) - curl (CVE-2019-5435 - http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5435)",
                        "action": "warn",
                        "policy_id": "48e6f7d6-1765-11e8-b5f9-8b6f228548b6",
                        "recommendation": "",
                        "rule_id": "6b5c14e7-a6f7-48cc-99d2-959273a2c6fa",
                        "allowlisted": false,
                        "allowlist_match": null,
                        "inherited_from_base": false
                    }
                ]
                ...
            }
            ...
        }
        ...
    ]
}
  • Dockerfile directive 'HEALTHCHECK' not found, matching condition 'not_exists' check is triggered by both images and hence inherited_from_base is marked true
  • MEDIUM Vulnerability found in os package type (APKG) - curl (CVE-2019-5435 - http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5435) is not triggered by the base image and therefore the value of inherited_from_base is false

2 - Compare Base Image Security Vulnerabilities

This feature provides a mechanism to compare the security vulnerabilities detected in an image with those of a base image. You can read more about base images and how to find them here. The API yields a response similar to vulnerabilities API with an additional element within each result to indicate whether the result is inherited from the base image.

Usage

This functionality is currently available via the Enterprise UI and API. Watch this space as we add base comparison support in other tools.

API

Refer to API Access section for the API specification. The vulnerabilities API GET /v2/images/{image_digest}/vuln/{vtype} has a base_digest query parameter that can be used to specify an image to compare vulnerability findings to. When this query parameter is provided an additional inherited_from_base field is provided for each vulnerability.

Example request using curl to retrieve security vulnerabilities for an image digest sha:xyz and compare the results to a base image digest sha256:abc

curl -X GET -u {username:password} "http://{servername:port}/v2/images/sha256:xyz/vuln/all?base_digest=sha256:abc"

Example output:

{
  "base_digest": "sha256:abc",
  "image_digest": "sha256:xyz",
  "vulnerability_type": "all",
  "vulnerabilities": [
    {
      "feed": "vulnerabilities",
      "feed_group": "alpine:3.12",
      "fix": "7.62.0-r0",
      "inherited_from_base": true,
      "nvd_data": [
        {
          "cvss_v2": {
            "base_score": 6.4,
            "exploitability_score": 10.0,
            "impact_score": 4.9
          },
          "cvss_v3": {
            "base_score": 9.1,
            "exploitability_score": 3.9,
            "impact_score": 5.2
          },
          "id": "CVE-2018-16842"
        }
      ],
      "package": "libcurl-7.61.1-r3",
      "package_cpe": "None",
      "package_cpe23": "None",
      "package_name": "libcurl",
      "package_path": "pkgdb",
      "package_type": "APKG",
      "package_version": "7.61.1-r3",
      "severity": "Medium",
      "url": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16842",
      "vendor_data": [],
      "vuln": "CVE-2018-16842"
    },
    {
      "feed": "vulnerabilities",
      "feed_group": "alpine:3.12",
      "fix": "2.4.46-r0",
      "inherited_from_base": false,
      "nvd_data": [
        {
          "cvss_v2": {
            "base_score": 5.0,
            "exploitability_score": 10.0,
            "impact_score": 2.9
          },
          "cvss_v3": {
            "base_score": 7.5,
            "exploitability_score": 3.9,
            "impact_score": 3.6
          },
          "id": "CVE-2020-9490"
        }
      ],
      "package": "apache2-2.4.43-r0",
      "package_cpe": "None",
      "package_cpe23": "None",
      "package_name": "apache2",
      "package_path": "pkgdb",
      "package_type": "APKG",
      "package_version": "2.4.43-r0",
      "severity": "Medium",
      "url": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9490",
      "vendor_data": [],
      "vuln": "CVE-2020-9490"
    }
  ]
}

Note that inherited_from_base is a new element in the API response added to support base comparison. The assigned boolean value indicates whether the exact vulnerability is present in the base image. In the above example

  • CVE-2018-16842 affects libcurl-7.61.1-r3 package in both images, hence inherited_from_base is marked true
  • CVE-2019-5482 affects apache2-2.4.43-r0 package does not affect the base image and therefore inherited_from_base is set to false