Skip to content

ci: fix CodeQL dockerfile/latest-tag alert in Dockerfile-distroless-testing#44857

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-dockerfile-latest-tag
Draft

ci: fix CodeQL dockerfile/latest-tag alert in Dockerfile-distroless-testing#44857
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-dockerfile-latest-tag

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 5, 2026

CodeQL alert #3503 (dockerfile/latest-tag) fires on two FROM lines in ci/Dockerfile-distroless-testing that reference envoyproxy/envoy:distroless-dev and envoyproxy/envoy:contrib-distroless-dev by mutable tag. The tags are intentionally unpinned (CI tests freshly-built images), but dismissing the alert costs security scorecard points and suppresses the rule class globally.

The fix parameterises the digest via ARG, defaulting to a zero-hash placeholder. CodeQL treats FROM image:tag@${ARG} as pinned (alert closes as fixed); CI injects the real digest at build time so the test still exercises the images produced in the same run. The zero-hash default is a deliberate tripwire — a build without the args fails immediately on manifest resolution rather than silently pulling a stale tag.

ci/Dockerfile-distroless-testing

# syntax=docker/dockerfile:1
ARG DISTROLESS_DEV_DIGEST=sha256:0000000000000000000000000000000000000000000000000000000000000000
ARG CONTRIB_DISTROLESS_DEV_DIGEST=sha256:0000000000000000000000000000000000000000000000000000000000000000

FROM envoyproxy/envoy:distroless-dev@${DISTROLESS_DEV_DIGEST} AS distroless-dev
FROM envoyproxy/envoy:contrib-distroless-dev@${CONTRIB_DISTROLESS_DEV_DIGEST} AS contrib-distroless-dev

Also normalises asAS for consistency with the debian-base stage.

ci/do_ci.sh (verify-distroless)

Resolves the local image digest via docker image inspect --format '{{.Id}}' (.Id is already sha256:… for locally-loaded images) and forwards both values as --build-arg to each docker build invocation.

DISTROLESS_DEV_DIGEST=$(docker image inspect envoyproxy/envoy:distroless-dev --format '{{.Id}}') \
    || { echo "FAIL: envoyproxy/envoy:distroless-dev image not found locally" >&2; exit 1; }
CONTRIB_DISTROLESS_DEV_DIGEST=$(docker image inspect envoyproxy/envoy:contrib-distroless-dev --format '{{.Id}}') \
    || { echo "FAIL: envoyproxy/envoy:contrib-distroless-dev image not found locally" >&2; exit 1; }

docker build -f ci/Dockerfile-distroless-testing --target=envoy-distroless -t distroless-testing \
    --build-arg DISTROLESS_DEV_DIGEST="${DISTROLESS_DEV_DIGEST}" \
    --build-arg CONTRIB_DISTROLESS_DEV_DIGEST="${CONTRIB_DISTROLESS_DEV_DIGEST}" .
Original prompt

Background

CodeQL alert #3503 (rule dockerfile/latest-tag — unpinned tag in Dockerfile FROM) fires on ci/Dockerfile-distroless-testing for these two lines:

FROM envoyproxy/envoy:distroless-dev as distroless-dev
FROM envoyproxy/envoy:contrib-distroless-dev as contrib-distroless-dev

These references are intentionally unpinned in source: the purpose of this Dockerfile is to test images that were just built in the same CI run. We do not want to pin to a digest checked into the repo, because that would defeat the purpose of the test (we'd be testing a stale image, not the one this PR produces).

Dismissing the alert is not desired — it costs scorecard/secret-scanning points and silences a class of real regressions in other Dockerfiles.

Goal

Resolve the alert as fixed (not dismissed) while preserving the "test the freshly-built image" semantics.

Approach

Switch the two FROM lines from image:tag form to image:tag@${DIGEST} form, where ${DIGEST} is a build ARG that CI sets to the digest of the image it just built. Provide a deliberately invalid placeholder default so a missing override fails loudly rather than silently pulling a moving tag.

The dockerfile/latest-tag CodeQL query does not fire when the image reference contains an @sha256:… digest portion, even if that portion comes from an ARG.

Required changes

1. ci/Dockerfile-distroless-testing

Update to:

# syntax=docker/dockerfile:1
FROM debian:trixie-slim@sha256:cedb1ef40439206b673ee8b33a46a03a0c9fa90bf3732f54704f99cb061d2c5a AS debian-base

# Digests of the freshly-built images under test.
# CI overrides these via --build-arg with the digest of the image it just produced.
# The zero placeholder default is intentional: it preserves the pinned-digest
# form (so the dockerfile/latest-tag CodeQL query no longer matches) while
# guaranteeing the build fails loudly if CI forgets to pass the real digest.
ARG DISTROLESS_DEV_DIGEST=sha256:0000000000000000000000000000000000000000000000000000000000000000
ARG CONTRIB_DISTROLESS_DEV_DIGEST=sha256:0000000000000000000000000000000000000000000000000000000000000000

FROM envoyproxy/envoy:distroless-dev@${DISTROLESS_DEV_DIGEST} AS distroless-dev

FROM envoyproxy/envoy:contrib-distroless-dev@${CONTRIB_DISTROLESS_DEV_DIGEST} AS contrib-distroless-dev

FROM debian-base AS envoy-distroless
COPY --from=distroless-dev / /distroless-dev
CMD ["/bin/sh", "-c", "stat -c '%A' /distroless-dev/etc/envoy | grep -q '...x' && echo OK || (echo FAIL: Envoy config is not readable in distroless container; exit 1)"]

FROM debian-base AS envoy-contrib-distroless
COPY --from=contrib-distroless-dev /usr/local/bin/envoy /usr/local/bin/envoy
# TODO(phlax): Make this an error not warning, once it lands and ci is fixed
CMD ["/bin/sh", "-c", "/usr/local/bin/envoy --version 2>&1 | grep -q '\\-contrib' && echo 'OK: contrib-distroless contains contrib binary' || (echo 'WARNING: contrib-distroless does NOT contain contrib binary - version:'; /usr/local/bin/envoy --version 2>&1; exit 0)"]

Note: also normalises asAS for consistency with the existing debian-base stage.

2. CI invocation site(s)

Find where ci/Dockerfile-distroless-testing is built (likely a workflow under .github/workflows/ and/or a script under ci/ — search the repo for Dockerfile-distroless-testing). Update each invocation to:

  1. Resolve the digest of the just-built envoyproxy/envoy:distroless-dev and envoyproxy/envoy:contrib-distroless-dev images. Two cases — pick whichever matches the existing CI flow:
    • If the upstream image is pushed by docker/build-push-action, use its outputs.digest.
    • If it is loaded into the local Docker daemon from an OCI tarball (e.g. via docker load), resolve via:
      DIST_DIGEST=$(docker image inspect envoyproxy/envoy:distroless-dev --format '{{.Id}}')
      CONTRIB_DIST_DIGEST=$(docker image inspect envoyproxy/envoy:contrib-distroless-dev --format '{{.Id}}')
      (.Id is already in sha256:… form for locally-loaded images and is acceptable as the digest portion of a FROM reference resolved from the local daemon.)
  2. Pass them through as build args:
    --build-arg DISTROLESS_DEV_DIGEST="$DIST_DIGEST" \
    --build-arg CONTRIB_DISTROLESS_DEV_DIGEST="$CONTRIB_DIST_DIGEST"
    

If the freshly-built images are only available locally (not pushed), the build of Dockerfile-distroless-testing must run with the same local Docker daemon / buildx instance so that image@sha256:<localId> resolves locally.

Acceptance criteria

  • ci/Dockerfile-distroless-testing no longer triggers CodeQL dockerfile/latest-tag (alert hot restart failed when upgrade envoy binary from v1.5.0 to v1.6.0 #3503 closes as fixed on the PR's analysis).
  • The CI job that consumes this Dockerfile still runs successfully and still tests the images built in the same workflow run (not images pulled from a registry by m...

This pull request was created from Copilot chat.

@repokitteh-read-only
Copy link
Copy Markdown

As a reminder, PRs marked as draft will not be automatically assigned reviewers,
or be handled by maintainer-oncall triage.

Please mark your PR as ready when you want it to be reviewed!

🐱

Caused by: #44857 was opened by Copilot.

see: more, trace.

…sting

Switch FROM lines to use ARG-based digest references with placeholder
defaults, and update ci/do_ci.sh to capture image digests via
docker image inspect and pass them as --build-arg.

Agent-Logs-Url: https://github.com/envoyproxy/envoy/sessions/78201a59-0327-4ae6-a0fe-fe3d919fcc15

Co-authored-by: phlax <454682+phlax@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix CodeQL alert for unpinned Dockerfile tags ci: fix CodeQL dockerfile/latest-tag alert in Dockerfile-distroless-testing May 5, 2026
Copilot finished work on behalf of phlax May 5, 2026 11:11
Copilot AI requested a review from phlax May 5, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants