Skip to content

sec(build): Dockerfile.dev still downloads a prebuilt migrate binary, and an older one (v4.17.0) #203

Description

@cristim

Surfaced while verifying LeanerCloud/cloud-commitments-cli#1835. Same defect class as LeanerCloud/cloud-commitments-cli#1833, in a file that does not ship to production.

What

Dockerfile.dev:29 still downloads a prebuilt golang-migrate release rather than compiling it on the pinned toolchain, and it is pinned to an older version than production used: v4.17.0 (production was v4.19.1 before LeanerCloud/cloud-commitments-cli#1835 replaced the download entirely).

Dockerfile.test has no such download and needs no change.

Why it matters, and why it is not urgent

This is the exact mechanism behind LeanerCloud/cloud-commitments-cli#1833: an upstream prebuilt binary carries whatever toolchain upstream built it with, so no base-image bump touches it. On production that meant /usr/local/bin/migrate shipping go1.25.4 with all seven stdlib advisories from LeanerCloud/cloud-commitments-cli#1833 and 62 more, executing on every container start.

Dockerfile.dev is a developer image. It does not reach production, which is why LeanerCloud/cloud-commitments-cli#1835 deliberately left it alone rather than widening a security PR's diff. But an older prebuilt release is very likely to carry at least the same advisories, and developer machines run it against local databases.

Fix direction

Mirror what LeanerCloud/cloud-commitments-cli#1835 did in the production Dockerfile:

RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
      go install -tags=postgres github.com/golang-migrate/migrate/v4/cmd/migrate@<version>

Note the wrinkle LeanerCloud/cloud-commitments-cli#1835 hit: go install refuses GOBIN when cross-compiling and writes to bin/${GOOS}_${GOARCH}/ instead, so both layouts must be resolved and the final mv should fail the build if neither produced a binary. Copy that shape rather than re-deriving it.

Keep the version in step with MIGRATE_VERSION in the Makefile, as the production Dockerfile's comment now says.

Verification bar

Build the dev image and read the binary, do not infer from the tag: go version -m /usr/local/bin/migrate must report the pinned toolchain. Then govulncheck -mode=binary against it, asserting on the summary line or JSON OSV entries rather than a bare grep -c.

Related: LeanerCloud/cloud-commitments-cli#1833, LeanerCloud/cloud-commitments-cli#1835, LeanerCloud/cloud-commitments-cli#1836 (nothing scans the images we build).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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