diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 76e88cf7..bc6d0604 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,6 +170,18 @@ jobs: format: 'table' trivy-config: trivy.yaml + # Mirror of the release-time pre-publish smoke gate in docker-publish.yml. + # Catches the class of failure where the source-built Docker CLI or + # Compose plugin compiles cleanly but does not exec at runtime (e.g. -o + # pointed at a non-main Go package, ABI breakage in a base image bump). + # The release workflow additionally polls /api/health; PR CI keeps just + # the binary check to bound job duration without losing the gate. + - name: Smoke test built image (binaries) + run: | + set -euo pipefail + docker run --rm --entrypoint sh sencho:pr-test -c \ + 'docker --version && docker compose version' + # --------------------------------------------------------------------------- # E2E Tests (PRs only, skipped for release-please PRs) # --------------------------------------------------------------------------- diff --git a/.trivyignore b/.trivyignore index 8c8cb747..ad13b99c 100644 --- a/.trivyignore +++ b/.trivyignore @@ -23,3 +23,14 @@ # BSD operating systems and Sencho ships linux/amd64 + linux/arm64 only. # See security/vex/sencho.openvex.json for the full impact statement. CVE-2026-39883 + +# Justification: covered by VEX statement for CVE-2026-34040 (Moby authz +# bypass on oversized request body). compose v5.1.2 bundles the legacy +# github.com/docker/docker@v28.5.2+incompatible as a client-side library +# for API types and codecs; the daemon-side authz hook code path the CVE +# affects is unreachable from a CLI client. The advisory's fix in +# Docker Engine 29.3.1 ships under the new github.com/moby/moby/v2 +# module path which compose v5.1.2 does not yet import, so v28.5.2 is +# the only Go-module-resolvable version reachable from compose. See +# security/vex/sencho.openvex.json for the full impact statement. +CVE-2026-34040 diff --git a/Dockerfile b/Dockerfile index 46f92427..948b6929 100644 --- a/Dockerfile +++ b/Dockerfile @@ -144,12 +144,39 @@ WORKDIR /src/docker-compose RUN mkdir -p /build +# Build target is ./cmd (the package main with plugin.Run), per docker/compose +# v5.1.2's Makefile. The directory ./cmd/compose is package compose (cobra +# command definitions only, not main). The module path moved from /v2 to /v5 +# in the v5 release, so the Version ldflag must reference /v5/internal. +# +# The bundled github.com/docker/docker dependency stays at v28.5.2+incompatible +# (compose v5.1.2's go.mod). It cannot be upgraded to docker-v29.3.1 (the +# release that contains the CVE-2026-34040 authz fix) because moby/moby's +# docker-29.x branch declares its module path as github.com/moby/moby/v2, +# making it unreachable through the legacy github.com/docker/docker import +# that compose v5.1.2 still uses. The Go module proxy reflects this and lists +# v28.5.2+incompatible as the highest resolvable version. The CVE only affects +# Docker Engine's daemon authz hook code path; compose runs as a CLI client +# and never executes that path. See security/vex/sencho.openvex.json for the +# full not_affected justification, which Trivy honours via trivy.yaml. RUN --mount=type=cache,id=go-mod,sharing=locked,target=/go/pkg/mod \ CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \ - -ldflags "-extldflags=-static \ - -X github.com/docker/compose/v2/internal.Version=v5.1.2" \ + -trimpath \ + -ldflags "-s -w -extldflags=-static \ + -X github.com/docker/compose/v5/internal.Version=v5.1.2" \ -o /build/docker-compose \ - ./cmd/compose + ./cmd + +# Sanity check: fail the stage immediately if go build did not produce an ELF +# executable. Catches the failure mode where -o file points to a non-main +# package and Go writes an ar-format archive that passes COPY + chmod but is +# not exec-able by the kernel, surfacing only as an opaque plugin-not-found +# error from the Docker CLI plugin manager hundreds of build steps later. +# `od -tx1` is used instead of `-c` because busybox and GNU coreutils render +# `-c` with different field padding; hex output is stable across both. +RUN test -f /build/docker-compose \ + && magic=$(dd if=/build/docker-compose bs=1 count=4 status=none | od -An -tx1 | tr -d ' \n') \ + && [ "$magic" = "7f454c46" ] # Stage 5: Production runtime # Runs on the TARGET platform - no compilation happens here. diff --git a/security/vex/sencho.openvex.json b/security/vex/sencho.openvex.json index 41cf1491..2c48dd6d 100644 --- a/security/vex/sencho.openvex.json +++ b/security/vex/sencho.openvex.json @@ -4,8 +4,8 @@ "author": "Studio Saelix", "role": "Vendor", "timestamp": "2026-04-26T00:00:00Z", - "last_updated": "2026-04-26T00:00:00Z", - "version": 1, + "last_updated": "2026-04-27T00:00:00Z", + "version": 2, "statements": [ { "vulnerability": { @@ -18,7 +18,7 @@ "@id": "pkg:oci/sencho", "subcomponents": [ { - "@id": "pkg:golang/github.com/docker/docker@v28.5.2", + "@id": "pkg:golang/github.com/docker/docker@v28.5.2+incompatible", "location": "/usr/local/lib/docker/cli-plugins/docker-compose" } ] @@ -26,7 +26,7 @@ ], "status": "not_affected", "justification": "vulnerable_code_not_in_execute_path", - "impact_statement": "The authz bypass applies to Docker daemon plugin authorization hooks. docker-compose v5.1.2 statically bundles docker/docker v28.5.2 as a library but never acts as a daemon and never runs authorization hooks. Sencho invokes compose only for up/down/ps operations against local user-authored compose files. The daemon authz code path is not reachable." + "impact_statement": "The authz bypass affects Docker Engine's daemon-side plugin authorization hook on oversized request bodies. docker-compose v5.1.2 statically bundles docker/docker v28.5.2+incompatible as a client-side library for API types and codecs; it never acts as a daemon and never runs authorization hooks. Sencho invokes compose only for up/down/ps operations against local user-authored compose files. The daemon authz code path is not reachable. Note on remediation: the advisory's 'fixed in 29.3.1' refers to Docker Engine the daemon product. The Go library that contains the corresponding source fix is github.com/moby/moby/v2 (a new module path adopted on the docker-29.x branch), not github.com/docker/docker which compose v5.1.2 still imports. Until upstream compose migrates to the v2 import path the v28.5.2+incompatible bundled library is the only Go-module-resolvable version, and the not_affected status is the principled triage rather than a deferred upgrade." }, { "vulnerability": {