Fixing CVEs for Golang-based statically-linked Executables

Last update: 2023-11-09 07:27:26 +0800 +0800
tags: Cve | Docker
Available translations: 日本語 / 中文(简体) / 中文(繁體)

gosu is a container-friendly alternative to su/sudo written in go. It’s included in the base image one of our production image, which triggers https://nvd.nist.gov/vuln/detail/CVE-2025-68121.

Generic Considerations for all Golang-based statically-linked Executables #

CVEs in a statically-linked golang program come from 2 sources:

  1. The software’s own code. This is just good old software CVEs
  2. golang standard SDK; official announcements. These CVEs exist in the toolchain used to build a specific executable.

Most times the Golang SDK is the one to blame, and fixing such CVEs is as simple as rebuild the program with latest golang SDK.

We are taking gosu as an example, but you can think about any statically linked executable:

sh
#!/bin/bash

set -eux

CONT_NAME=tmp_mysqlcontainer

docker create --pull=always --name $CONT_NAME mysql:latest 
docker cp $CONT_NAME:/usr/local/bin/gosu /tmp/gosu
docker run -it --rm -v /tmp/gosu:/tmp/gosu golang:latest

and within the docker:

sh
ldd /tmp/gosu/gosu
#	not a dynamic executable
go version /tmp/gosu/gosu
# /tmp/gosu/gosu: go1.24.6

Since https://nvd.nist.gov/vuln/detail/CVE-2025-68121 which affects all golang version below 1.24.13, we are sure this very program is build by a vulnerable goalng toolchain.

The real world problem #

There are software maintainers who refuse to rebuild their binary release constantly. The main argument is that their code doesn’t call affected golang standard libraries. The official CVE checker golang.org/x/vuln/cmd/govulncheck@latest report CVEs based on function invocation path, instead of simple golang version number that built the program:

sh
go run golang.org/x/vuln/cmd/govulncheck@latest -mode=binary /tmp/gosu/gosu
# === Symbol Results ===
# 
# No vulnerabilities found.
# 
# Your code is affected by 0 vulnerabilities.
# This scan also found 2 vulnerabilities in packages you import and 31
# vulnerabilities in modules you require, but your code doesn't appear to call
# these vulnerabilities.
# Use '-show verbose' for more details.

While this argument makes sense, depending on the security policy of your working environment, you may or may not be able to get away with this.

The Fix #

  • For a quick fix, just drop the gosu if you don’t need it:

    dockerfile
    RUN rm /usr/local/bin/gosu
  • otherwise, your image requires such a binary to work properly, and you hit the hard path. As a generic fix for any statically-linked executable, build one from source (e.g. as part of the image’s CICD pipeline or Dockerfile) by yourself with latest golang SDK. Most times you just want to fix some CVEs (that happened to do with golang while you are not a golang expert) real quicks, when your containerized system has nothing to do with go. That take extra effort so good luck on that one.

reference:

Comments

Read or comment on GitHub (sign-in required to comment)