Skip to content

sec(build): shipped image still builds on go1.26.5, so the stdlib CVEs remain in the artifact after #1832 #1833

Description

@cristim

Split out of #1829 so that the CI unblock (#1832, a 3-line workflow bump) could land immediately while main was red and every open PR was blocked behind it.

#1832 makes CI green. It does not fix the shipped artifact. Recording that gap here rather than letting a green pipeline imply the exposure is resolved.

What is still on go1.26.5

1. The production container image (the part that actually ships)

  • Dockerfile:18 — FROM --platform=$BUILDPLATFORM golang:1.26.5-alpine3.24@sha256:0178a641fbb4858c5f1b48e34bdaabe0350a330a1b1149aabd498d0699ff5fb2 AS builder
  • Dockerfile.dev:8 and Dockerfile.test:8 — same base image and digest

The binary we build and deploy is therefore compiled against the go1.26.5 standard library and contains all 7 advisories from #1829: GO-2026-6218 (net/url), GO-2026-6091 (html/template), GO-2026-6090 (crypto/tls), GO-2026-6089 and GO-2026-5026 (net/http), GO-2026-6088 (encoding/xml), GO-2026-5972 (encoding/asn1).

Measured per-module on go1.26.5 with govulncheck v1.1.4 (the CI-pinned version), before #1832: root module 7 vulnerabilities, pkg 5, providers/aws 5, providers/azure 6, providers/gcp 4, tests/e2e clean. On go1.26.6 all six report No vulnerabilities found.

2. The go directives

go.work:1, go.mod:3, pkg/go.mod:3, providers/{aws,azure,gcp}/go.mod:3 are all go 1.26.5 (tests/e2e/go.mod is go 1.25).

This matters for the three workflows that use go-version-file: go.mod rather than the GO_VERSION env var: database-migration.yml (three call sites), aws_sanity.yml, azure_sanity.yml. setup-go resolves the toolchain from the go directive there, so those jobs plausibly still install 1.26.5 even after #1832. Confirm this empirically before deciding whether the directive bump is required or merely tidy; GOTOOLCHAIN=auto only ever upgrades, never downgrades, so the interaction is worth measuring rather than reasoning about.

Constraints on the fix

  • Do not drop the SHA256 digest pin to make the bump easy. It exists so that a registry tag mutation cannot poison the build (Docker Hub permits re-tagging). Resolve the real digest for the new tag via docker buildx imagetools inspect golang:1.26.6-alpine3.24 or the Docker Hub tags API. Never guess or fabricate a digest.
  • Confirm an alpine3.24 variant exists for 1.26.6 before pinning that exact tag shape. 1.26.6 is the top of the 1.26 line; there is no 1.26.7 as of filing.
  • No suppression anywhere: no ignore list, no -scan narrowing, no continue-on-error.

Verification bar

  • Rebuild the image and confirm the resulting binary reports clean, rather than inferring it from the base tag alone.
  • Re-run the per-module govulncheck loop and capture exit codes explicitly into variables. An empty output with a nonzero exit is a failed run, not a clean one, and ${PIPESTATUS[0]} after a subshell can silently yield an empty value.
  • Watch for collateral from the directive bump: Lint Code uses golangci-lint pinned at v2.10.1 and is toolchain-sensitive, and gosec is pinned at v2.28.0. Reproduce both at those exact versions; a newer local golangci-lint has a different bundled ruleset and gives a false exit 0.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions