Point default helper image tag at latest Alpine base
What this does
Repoints the unsuffixed default helper image tag (for example
x86_64-vX.Y.Z) from the alpine3.21-* build to the alpine-latest-*
build in scripts/pusher/helper-images.json.
Today the default tag aliases the Alpine 3.21 build, whose git-lfs apk
(git-lfs-3.6.0-r5) is statically linked against go1.23.9 and carries
reachable Go stdlib DoS CVEs. The alpine-latest build (Alpine 3.23,
git-lfs on go1.25.10) already exists and clears them. Alpine 3.21
remains available as an explicit alpine3.21-x86_64-vX opt-in.
This matches behavior already documented in
docs/configuration/advanced-configuration.md (lines 2205-2206: in
GitLab Runner 18.4 and later, alpine is an alias for alpine-latest)
and follows the precedent in
!5995 (merged)
(commit 5eaadd3f7315c31af2dd2b91ff03c7471e67f9cb), which did the
identical move from alpine3.19-* to alpine3.21-*.
How helper-images.json works (the counterintuitive part)
The default block maps component (a real built image) -> list of tag
templates that image is published under. The mapping reads "backwards"
from how you pull: the key is the image, the values are labels stuck on
it. A tag template does not need to contain the flavor name to point at
that flavor's image; the % is replaced by the version fragment at push
time.
For x86_64 at version v19.0.1, the entry on main is:
"alpine3.21-x86_64": [
"alpine3.21-x86_64-%",
"x86_64-%"
]That means the Alpine 3.21 image is published under both
alpine3.21-x86_64-v19.0.1 (the explicit pin) and the bare
x86_64-v19.0.1 (the default alias). So docker pull ...:x86_64-v19.0.1
resolves to the 3.21 image even though the tag name has no 3.21 in it.
That is the bug.
This MR moves the bare x86_64-% template onto the alpine-latest image:
"alpine3.21-x86_64": [
"alpine3.21-x86_64-%"
],
"alpine-latest-x86_64": [
"alpine-latest-x86_64-%",
"x86_64-%"
]It is a move, not a copy: a tag template must have exactly one owning
component. If x86_64-% were listed under two components, both images
would be pushed to the same tag concurrently and the result would be a
last-writer-wins race (see pushImages in scripts/pusher/main.go).
Removing it from alpine3.21-x86_64 while adding it to
alpine-latest-x86_64 keeps a single owner. The explicit
alpine3.21-x86_64-v19.0.1 tag still exists, so pinners are unaffected.
Changes
scripts/pusher/helper-images.json: move the 7 unsuffixed alias templates (x86_64-%,arm64-%,arm-%,ppc64le-%,riscv64-%,s390x-%,x86_64-%-pwsh) fromalpine3.21-*toalpine-latest-*.docs/executors/kubernetes/_index.md: update thehelper_image_flavordescription soalpineis documented as an alias foralpine-latest.
Validation
scripts/pushermodule unit tests pass (go test).- Local resolution test (not committed): loads the real edited
manifest through the production tag-resolution code and asserts the 7
unsuffixed aliases resolve to
alpine-latest-*and notalpine3.21-*. - Local end-to-end push test (not committed): generates a
uniquely-digested stub image per component, runs the real pusher push
code against the real manifest into a local
registry:2, then queries the registry and asserts the barex86_64-vTESTtag has the same digest asalpine-latest-x86_64-vTESTand a different digest fromalpine3.21-x86_64-vTEST. Both tests fail on the pre-change manifest and pass after the fix. (Happy to contribute a committed version of one of these if reviewers want manifest coverage in CI.) - Reproduced against the published
v19.0.1images via Docker:- default
x86_64-v19.0.1==alpine3.21-x86_64-v19.0.1(digest3f15fbd4...): Alpine 3.21.7,git-lfs/3.6.0,go 1.23.9. alpine-latest-x86_64-v19.0.1(digestfecc46c3...): Alpine 3.23.4,git-lfs/3.7.0,go 1.25.10.
- default
Note for reviewers
This work item is labeled security / bug::vulnerability
(https://gitlab.com/gitlab-org/gitlab-runner/-/work_items/39553). This MR
was opened against the canonical project. If the team prefers to route
this through the security release process / security fork, let me know
and I will move it.
Related: https://gitlab.com/gitlab-org/gitlab-runner/-/work_items/39553