Intro

There are multiple tools that can be used to scan existing containers for CVEs.

Trivy

Trivy is an open-source solution. To scan the image, download it first so that it is available locally.

Unfortunately, Trivy cannot scan image contents, Java libraries, and the SBOM (Software Bill of Materials) in a single step.

Image and Java

Docker image metadata and Java libraries which are present in the image can be scanned using image mode.

$ docker pull docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444
23.3.0: Pulling from pdm/central/pdm_control
Digest: sha256:4f5bdd3bcee31586de9f741294604bde9593adc10460b8836d8478c0dc824400
Status: Image is up to date for docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444
docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444

To start the scan, run the following command.

JSON report
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ \
-v $(pwd):/workspace \
aquasec/trivy:latest image \
--format json \
--output /workspace/report.json \
docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444

Please note that Trivy needs to download a vulnerability database (~800 MB). To avoid downloading it during every scan, we store it, together with other cached data, in the trivy-cache volume. For some reason, a bind mount does not work because of permission issues.

The report is then stored in the current directory.

HTML report
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ \
-v $(pwd):/workspace \
aquasec/trivy:latest image \
--format template \
--template "@contrib/html.tpl" \
--output /workspace/report.html \
docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444

HTML report can be found in /workspace which is mounted to current directory.

SBOM

The Software Bill of Materials generated by the npm build needs to be scanned separately. Unfortunately, an SBOM file inside the container cannot be scanned directly.

A command to scan the SBOM would look like this:

Text report
docker run --rm -v trivy-cache:/root/.cache/ -v "${PWD}/files:/workspace" aquasec/trivy:latest sbom /workspace/sbom.json
JSON report
docker run --rm \
-v trivy-cache:/root/.cache/ \
-v "$(pwd)/files:/workspace" \
aquasec/trivy:latest \
sbom /workspace/sbom.json --format json --output /workspace/report.json
HTML report
docker run --rm \
-v trivy-cache:/root/.cache/ \
-v "$(pwd)/files:/workspace" \
aquasec/trivy:latest \
sbom /workspace/sbom.json --format template --template "@contrib/html.tpl" --output /workspace/report.html

To get both reports, the scanner needs to be run twice.

# Run Docker image and JAR scan
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ \
-v $(pwd):/workspace \
aquasec/trivy:latest image --format json -o /workspace/report-image.json docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444


# Extract sbom from container and run sbom (npm)
docker run --rm docker.rtb-bl.de/pdm/central/pdm_control:dev-next-2444 sh -c 'cat ui/ngapp/sbom.json' > sbom.json
run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ \
-v $(pwd):/workspace \
aquasec/trivy:latest sbom --format json --output /workspace/report-sbom.json /workspace/sbom.json

Then merge the two reports into one file.

jq -s '{SchemaVersion: .[0].SchemaVersion, ArtifactName: "Kombinovaný Report", ArtifactType: .[0].ArtifactType, Results: ([.[].Results] | flatten)}' report-image.json report-json.json > report-all.json

Then convert the resulting JSON to HTML.

docker run --rm -v "$(pwd)":/workspace aquasec/trivy:latest \
convert --format template --template "@contrib/html.tpl" --output /workspace/report-cve.html /workspace/report-all.json

Snyk

This is a commercial tool. API key is required.