Recently I was learning about the Chainguard tooling for reducing vulnerabilities in containers.
It started via their course, which was announced few days ago in 14th February 2024 at “New Chainguard Academy course: Painless Vulnerability Management”. It is currently free of charge, but might change at some point.
Chainguard is also providing Docker images that have dramatically reduced the number of known vulnerabilities, that can be seen for example here “Vulnerability Comparison: rust”.
In order to know what to change if there are vulnerabilities, first those vulnerabilities need to be found.
Scan images to find known vulnerabilities
Three scanners were mentioned in the course:
Scanning rust:alpine
image as an example. The image is available at Docker Hub,
where it is noted under “Vulnerabilities” section:
No Vulnerabilities Found
However running the scanner grype rust:alpine
, reveals the following results:
✔ Cataloged contents
├── ✔ Packages [29 packages]
├── ✔ File digests [1,067 files]
├── ✔ File metadata [1,067 locations]
└── ✔ Executables [105 executables]
✔ Scanned for vulnerabilities [13 vulnerability matches]
├── by severity: 0 critical, 1 high, 12 medium, 0 low, 0 negligible
└── by status: 0 fixed, 13 not-fixed, 0 ignored
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
binutils 2.41-r0 apk CVE-2023-25584 High
busybox 1.36.1-r15 apk CVE-2023-42366 Medium
busybox 1.36.1-r15 apk CVE-2023-42365 Medium
busybox 1.36.1-r15 apk CVE-2023-42364 Medium
busybox 1.36.1-r15 apk CVE-2023-42363 Medium
busybox-binsh 1.36.1-r15 apk CVE-2023-42366 Medium
busybox-binsh 1.36.1-r15 apk CVE-2023-42365 Medium
busybox-binsh 1.36.1-r15 apk CVE-2023-42364 Medium
busybox-binsh 1.36.1-r15 apk CVE-2023-42363 Medium
ssl_client 1.36.1-r15 apk CVE-2023-42366 Medium
ssl_client 1.36.1-r15 apk CVE-2023-42365 Medium
ssl_client 1.36.1-r15 apk CVE-2023-42364 Medium
ssl_client 1.36.1-r15 apk CVE-2023-42363 Medium
The output from running trivy image rust:alpine
states that there would be no vulnerabilities:
rust:alpine (alpine 3.19.1)
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
The third scanner results after running scorecard --repo=github.com/rust-lang/docker-rust
this output:
RESULTS
-------
Aggregate score: 5.8 / 10
Check scores:
|---------|------------------------|--------------------------------|
| SCORE | NAME | REASON |
|---------|------------------------|--------------------------------|
| 10 / 10 | Binary-Artifacts | no binaries found in the repo |
|---------|------------------------|--------------------------------|
| 0 / 10 | Branch-Protection | branch protection not enabled |
| | | on development/release |
| | | branches |
|---------|------------------------|--------------------------------|
| 1 / 10 | CI-Tests | 2 out of 12 merged PRs |
| | | checked by a CI test -- score |
| | | normalized to 1 |
|---------|------------------------|--------------------------------|
| 0 / 10 | CII-Best-Practices | no effort to earn an OpenSSF |
| | | best practices badge detected |
|---------|------------------------|--------------------------------|
| 8 / 10 | Code-Review | found 2 unreviewed changesets |
| | | out of 14 -- score normalized |
| | | to 8 |
|---------|------------------------|--------------------------------|
| 10 / 10 | Contributors | 17 different organizations |
| | | found -- score normalized to |
| | | 10 |
|---------|------------------------|--------------------------------|
| 10 / 10 | Dangerous-Workflow | no dangerous workflow patterns |
| | | detected |
|---------|------------------------|--------------------------------|
| 0 / 10 | Dependency-Update-Tool | no update tool detected |
|---------|------------------------|--------------------------------|
| 0 / 10 | Fuzzing | project is not fuzzed |
|---------|------------------------|--------------------------------|
| 0 / 10 | License | license file not detected |
|---------|------------------------|--------------------------------|
| 10 / 10 | Maintained | 21 commit(s) out of 30 and 1 |
| | | issue activity out of 30 found |
| | | in the last 90 days -- score |
| | | normalized to 10 |
|---------|------------------------|--------------------------------|
| ? | Packaging | no published package detected |
|---------|------------------------|--------------------------------|
| 0 / 10 | Pinned-Dependencies | dependency not pinned by hash |
| | | detected -- score normalized |
| | | to 0 |
|---------|------------------------|--------------------------------|
| 0 / 10 | SAST | SAST tool is not run on all |
| | | commits -- score normalized to |
| | | 0 |
|---------|------------------------|--------------------------------|
| 10 / 10 | Security-Policy | security policy file detected |
|---------|------------------------|--------------------------------|
| ? | Signed-Releases | no releases found |
|---------|------------------------|--------------------------------|
| 10 / 10 | Token-Permissions | GitHub workflow tokens follow |
| | | principle of least privilege |
|---------|------------------------|--------------------------------|
| 10 / 10 | Vulnerabilities | no vulnerabilities detected |
|---------|------------------------|--------------------------------|
Further documentation for each of the checks is available at the scanners GitHub repository.
Mitigate known vulnerabilities
The first scanner used above, grype
found one high severity level vulnerability in which I will focus here:
binutils 2.41-r0 apk CVE-2023-25584 High
The CVE specific information is available at cve.org, but in this case not much more than just this description:
An out-of-bounds read flaw was found in the parse_module function in bfd/vms-alpha.c in Binutils.
NIST has a bit more details on the given CVE.
The fix was made already in December 2022, while the CVE was created in September 2023. Process takes time, but good news is that the fix has been there for long.
Looking at the Alpine Linux packages repository, the version 2.42-r0
is already available for binutils
, but only as recently as 2024-02-19…
Given that the scanner container was a Docker image, which most likely would be used as a base for building
something in a Dockerfile
, so the mitigation in this case could be to update the dependencies with apk
.
# Use Alpine Linux as a base with Rust tools
FROM rust:alpine
# Upgrade Alpine Linux dependencies
RUN apk upgrade --no-cache
Trying this out:
docker build . -t rust-alpine-upgrade-apk-binutils
grype rust-alpine-upgrade-apk-binutils
Start the Docker container to check which version of binutils
has been taken in use
docker run -it rust-alpine-upgrade-apk-binutils busybox
apk info -vv | grep binutils
Surprisingly this still prints out the same version as found earlier:
binutils-2.41-r0 - Tools necesary to build programs
What also happened in this case, was that few days later when continuing on this topic, the CVE for
binutils
version 2.41-r0
was no longer shown via grype rust:alpine
…