Handling CVEs in the project

Handling CVEs in the project

Introduction

CVE, short for Common Vulnerabilities and Exposures, is a list of publicly disclosed computer security flaws. When someone refers to a CVE, they mean a security flaw that’s been assigned a CVE ID number.

CVEs filed on dependencies

Checking if a CVE applies to Ramen

Note: Ramen has two go modules, one for the main project and another for the api. You need to perform the check below for both the modules.

When a CVE is filed on a direct or an indirect dependency of Ramen, you will first have to check if it applies to a particular branch. Some of the CVE analysis tools make use of the go.sum file to make this determination and there might be false positives in those methods.

To check whether a package is really used in Ramen or not you can use the following command.

go mod why -m <module path>

This command shows only the shortest path to the module and there could be more usage of it elsewhere.

Here is an example of the command for three different scenarios

  1. When the module is used by Ramen directly. The output shows that the controllers package makes use of the time module and specifically the rate package in it.

    $ go mod why -m golang.org/x/time
    # golang.org/x/time
    github.com/ramendr/ramen/internal/controller
    golang.org/x/time/rate
    
  2. When the module is an indirect dependency

    $ go mod why -m github.com/go-logr/zapr
    # github.com/go-logr/zapr
    github.com/ramendr/ramen
    sigs.k8s.io/controller-runtime/pkg/log/zap
    github.com/go-logr/zapr
    
  3. When a module isn’t used by Ramen directly or indirectly. If a module isn’t used by Ramen then you can ignore the CVE.

    $ go mod why -m github.com/open-telemetry/opentelemetry-go-contrib
    # github.com/open-telemetry/opentelemetry-go-contrib
    (main module does not need module github.com/open-telemetry/opentelemetry-go-contrib)
    

Fixing the CVEs by updating the packages

  1. When a module is a direct dependency, then using go get to update the version of the module to the one that fixes the CVE is sufficient.

  2. When a module is an indirect dependency, you will have to determine if the module which brings in the transitive dependency has a fix for the CVE. If it does, you can update the version of the module to the one that fixes the CVE using go get. If it doesn’t, you will have to wait for the module to update the version of the transitive dependency or you can use a replace directive in the go.mod file to update the version of the transitive dependency.

CVEs filed on Golang

When a CVE is filed against Golang, you need to check both the upstream Ramen repository and the downstream container images.

Checking the upstream Ramen repository

Note: This check is only relevant for upstream container images built from the Ramen repository. Downstream builds use a different Dockerfile and build process, so this method does not apply to downstream images.

The relevant Go version for CVE checking is the one used to build the Ramen container image, not the go.mod compatibility version. Check the Dockerfile to see which Go version is used:

grep "FROM.*golang" Dockerfile

Example output:

FROM docker.io/library/golang:1.25 as builder

This shows the image uses Go 1.25, which will pick the latest 1.25.x patch version available. If a CVE was fixed in Go 1.25.7, the Ramen image is not affected even if go.mod specifies go 1.25.0.

Compare the Go version from the Dockerfile against the CVE fix versions to determine if the upstream code is vulnerable.

Checking downstream container images

Prerequisites

  • Access to the downstream container registry (e.g., quay.io/rhceph-dev)
  • podman or docker installed and authenticated

Step 1: Identify the downstream image

For ODF (OpenShift Data Foundation) builds, the downstream Ramen operator images are typically located at:

quay.io/rhceph-dev/odf4-odr-rhel9-operator:<version>

Where <version> corresponds to the ODF version.

Step 2: Pull the downstream image

Example for ODF 4.18:

podman pull quay.io/rhceph-dev/odf4-odr-rhel9-operator:v4.18

Step 3: Extract the Go version from the binary

The Go version is embedded in the compiled binary. Extract and check it using these commands:

podman run --rm --entrypoint cat quay.io/rhceph-dev/odf4-odr-rhel9-operator:v4.18 /manager > manager
go version manager
rm manager

Example output:

manager: go1.23.10 (Red Hat 1.23.10-11.el9)

This shows the binary was compiled with Go 1.23.10 from Red Hat’s patched distribution.

Note: This works because the Ramen image contains the cat executable.

Step 4: Compare against CVE fix versions

Once you have the Go version from the downstream image, compare it against the CVE fix versions:

  1. Check the CVE announcement for which Go versions include the fix
  2. Note that Red Hat’s Go builds may include backported security fixes
  3. Go versions from Red Hat (indicated by “Red Hat” in the version string) often have security patches backported to older minor versions