Limit High or Critical CVEs in your Images Workloads

How to use the vulnerability attestation with no High or Critical CVEs Policy

While Common Vulnerabilities and Exposures (CVEs) are undesirable at any time, the software security standards of certain industries strictly regulate the allowance of high or critical CVEs. For example, in the payment industry, the PCI Security Standards Council requires that all vulnerabilities with a Common Vulnerability Scoring System (CVSS) score higher than 4 are addressed.

For engineers and security professionals working in these contexts, it’s essential to know if container images have high or critical CVEs before deploying them. But tracking these CVEs manually can be difficult, especially when regularly pulling or updating large numbers of images for your workloads.

Policy solution: vulnerability attestation with no high or critical CVEs

One way of addressing this concern is to use Chainguard’s policy that checks an image’s attestation to determine whether the image has any high or critical CVEs. Used with an admissions controller (such as Chainguard Enforce or the open source Sigstore policy-controller), this policy enables you to restrict images or receive a warning whenever an image fails to meet the policy’s requirements.

For this policy to work, the image under inspection must have an attached attestation containing output from its vulnerability scan. These vulnerability attestations are typically generated by the upstream maintainer who inserts the output of an image’s vulnerability scan into a vulnerability attestation and then signs the attestation to assure downstream users of its integrity. If the image doesn’t have a vulnerability attestation or you want to double check the attestation, you can also create a vulnerability attestation yourself using a scanner like Trivy. In either case, the vulnerability attestation is checked by this policy to determine whether the image contains any high or critical vulnerabilities.

Here is the policy in full:

#############################################################################################
# To generate an attestation with a scan report and attest it to an image follow these steps:
# $ trivy image --format cosign-vuln --output vuln.json <IMAGE>
# $ cosign attest --key /path/to/cosign.key --type https://cosign.sigstore.dev/attestation/vuln/v1 --predicate vuln.json <IMAGE>
#
# $ cosign verify-attestation --key /path/to/cosign.pub --type --type https://cosign.sigstore.dev/attestation/vuln/v1 <IMAGE>
#############################################################################################
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: vuln-no-high-or-critical-rego
  annotations:
    catalog.chainguard.dev/title: Fail on high or critical CVEs
    catalog.chainguard.dev/description: Vulnerability attestation with no High or Critical CVEs
    catalog.chainguard.dev/labels: attestation,rego
spec:
  images:
    - glob: "**"
  authorities:
    - name: my-authority
      key:
          # REPLACE WITH YOUR PUBLIC KEY!
          data: |
            -----BEGIN PUBLIC KEY-----
            MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESWmPfv6b083TNcwY4SlYcZULn7jX
            /vfUyU7CPr2zssLc3+8SWAv2ZY59pofKnvYBp9dNiNwVTkrxab1bcpocVg==
            -----END PUBLIC KEY-----
      attestations:
        - name: must-not-have-high-critical-cves
          predicateType: https://cosign.sigstore.dev/attestation/vuln/v1
          policy:
            type: rego
            data: |
              package sigstore
              isCompliant[response] {
                input.predicateType = "https://cosign.sigstore.dev/attestation/vuln/v1"
                filteredHighSeverity = [c | c := input.predicate.scanner.result.Results[_].Vulnerabilities[_]; c.Severity == "HIGH"]
                filteredCriticalSeverity = [c | c := input.predicate.scanner.result.Results[_].Vulnerabilities[_]; c.Severity == "CRITICAL"]
                result = ((count(filteredHighSeverity) + count(filteredCriticalSeverity)) == 0)
                errorMsg = sprintf("Found HIGH '%d' and CRITICAL '%d' vulnerabilities", [count(filteredHighSeverity) ,count(filteredCriticalSeverity)])
                warnMsg = ""
                response := {
                  "result" : result,
                  "error" : errorMsg,
                  "warning" : warnMsg
                }
              }

Implementing this policy

You can use this policy freely with the open source Sigstore policy-controller to block new deployments of images that don’t meet the policy’s requirements.

However, if you are interested in making sure both incoming and already admitted images meet this policy, you may be interested in Chainguard Enforce. With Chainguard Enforce, all of your images will be continuously evaluated against your selected policies, even if they passed these policies when initially admitted. You can set Enforce to send a notification (including posting to Slack, or opening a GitHub issue) if and when a deployed image falls out of compliance so that corrective action may be taken.

To learn more about Chainguard Enforce, you can read the Enforce Overview and browse the Enforce documentation. You can also request access to the product by selecting Chainguard Enforce for Kubernetes on the inquiry form.

Last updated: 2023-04-12 15:22