From 5665ccb080b8c2ab93303c5c95b2df5000b6fc0f Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Sat, 27 Jun 2026 01:32:15 -0400 Subject: [PATCH 1/2] Shrink GitHub runner job image package --- cmd/github-actions-runner-job/Dockerfile | 25 ++++++++++--- cmd/github-actions-runner-job/entrypoint.sh | 12 +++++++ release_packaging_test.go | 39 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 cmd/github-actions-runner-job/entrypoint.sh diff --git a/cmd/github-actions-runner-job/Dockerfile b/cmd/github-actions-runner-job/Dockerfile index 3f9bb64..71bc959 100644 --- a/cmd/github-actions-runner-job/Dockerfile +++ b/cmd/github-actions-runner-job/Dockerfile @@ -1,13 +1,28 @@ -ARG ACTIONS_RUNNER_IMAGE=ghcr.io/actions/actions-runner:2.333.1 -FROM ${ACTIONS_RUNNER_IMAGE} +FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy ARG TARGETARCH +ARG ACTIONS_RUNNER_VERSION=2.333.1 ARG RUNNER_JOB_BINARY=dist/github-actions-runner-job-linux-${TARGETARCH} -USER root +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates curl git tar gzip bash \ + && rm -rf /var/lib/apt/lists/* + +RUN set -eux; \ + runner_arch="${TARGETARCH}"; \ + if [ "$runner_arch" = "amd64" ]; then runner_arch="x64"; fi; \ + mkdir -p /opt/actions-runner; \ + curl -fsSL \ + "https://github.com/actions/runner/releases/download/v${ACTIONS_RUNNER_VERSION}/actions-runner-linux-${runner_arch}-${ACTIONS_RUNNER_VERSION}.tar.gz" \ + -o /opt/actions-runner/actions-runner.tar.gz; \ + chmod 0644 /opt/actions-runner/actions-runner.tar.gz; \ + useradd -m -s /bin/bash runner + COPY --chmod=0755 ${RUNNER_JOB_BINARY} /usr/local/bin/github-actions-runner-job +COPY --chmod=0755 cmd/github-actions-runner-job/entrypoint.sh /usr/local/bin/github-actions-runner-job-entrypoint USER runner WORKDIR /home/runner -ENV GITHUB_ACTIONS_RUNNER_DIR=/home/runner -ENTRYPOINT ["/usr/local/bin/github-actions-runner-job"] +ENV GITHUB_ACTIONS_RUNNER_ARCHIVE=/opt/actions-runner/actions-runner.tar.gz +ENV GITHUB_ACTIONS_RUNNER_DIR=/home/runner/actions-runner +ENTRYPOINT ["/usr/local/bin/github-actions-runner-job-entrypoint"] diff --git a/cmd/github-actions-runner-job/entrypoint.sh b/cmd/github-actions-runner-job/entrypoint.sh new file mode 100644 index 0000000..d9158ef --- /dev/null +++ b/cmd/github-actions-runner-job/entrypoint.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +archive="${GITHUB_ACTIONS_RUNNER_ARCHIVE:-/opt/actions-runner/actions-runner.tar.gz}" +runner_dir="${GITHUB_ACTIONS_RUNNER_DIR:-/home/runner/actions-runner}" + +if [ ! -x "$runner_dir/config.sh" ]; then + mkdir -p "$runner_dir" + tar -xzf "$archive" -C "$runner_dir" +fi + +exec /usr/local/bin/github-actions-runner-job "$@" diff --git a/release_packaging_test.go b/release_packaging_test.go index 97417c6..e9bd676 100644 --- a/release_packaging_test.go +++ b/release_packaging_test.go @@ -91,6 +91,45 @@ func TestReleasePublishesGitHubActionsRunnerJobImage(t *testing.T) { } } +func TestGitHubActionsRunnerJobImageCarriesCompressedRunnerArchive(t *testing.T) { + data, err := os.ReadFile("cmd/github-actions-runner-job/Dockerfile") + if err != nil { + t.Fatalf("read runner job Dockerfile: %v", err) + } + dockerfile := string(data) + if strings.Contains(dockerfile, "ghcr.io/actions/actions-runner") { + t.Fatal("runner job image must not inherit the expanded actions-runner image; docker save exceeds workflow-compute package limits") + } + for _, want := range []string{ + "ARG ACTIONS_RUNNER_VERSION=", + "actions-runner-linux-${runner_arch}-${ACTIONS_RUNNER_VERSION}.tar.gz", + "GITHUB_ACTIONS_RUNNER_ARCHIVE=/opt/actions-runner/actions-runner.tar.gz", + "GITHUB_ACTIONS_RUNNER_DIR=/home/runner/actions-runner", + "COPY --chmod=0755 cmd/github-actions-runner-job/entrypoint.sh /usr/local/bin/github-actions-runner-job-entrypoint", + `ENTRYPOINT ["/usr/local/bin/github-actions-runner-job-entrypoint"]`, + } { + if !strings.Contains(dockerfile, want) { + t.Fatalf("runner job Dockerfile must include %q", want) + } + } + + entrypoint, err := os.ReadFile("cmd/github-actions-runner-job/entrypoint.sh") + if err != nil { + t.Fatalf("read runner job entrypoint: %v", err) + } + entrypointText := string(entrypoint) + for _, want := range []string{ + "${GITHUB_ACTIONS_RUNNER_ARCHIVE:-/opt/actions-runner/actions-runner.tar.gz}", + "${GITHUB_ACTIONS_RUNNER_DIR:-/home/runner/actions-runner}", + `tar -xzf "$archive" -C "$runner_dir"`, + `exec /usr/local/bin/github-actions-runner-job "$@"`, + } { + if !strings.Contains(entrypointText, want) { + t.Fatalf("runner job entrypoint must include %q", want) + } + } +} + func TestReleaseArchiveCheckRejectsProviderBuildOutsideArchive(t *testing.T) { config := ` builds: From d8014e136841a59ea4280589e03d82d9c13e674d Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Sat, 27 Jun 2026 01:45:33 -0400 Subject: [PATCH 2/2] Harden runner archive image startup --- cmd/github-actions-runner-job/Dockerfile | 9 ++++++++- cmd/github-actions-runner-job/entrypoint.sh | 7 ++++++- release_packaging_test.go | 9 ++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/cmd/github-actions-runner-job/Dockerfile b/cmd/github-actions-runner-job/Dockerfile index 71bc959..e10fc24 100644 --- a/cmd/github-actions-runner-job/Dockerfile +++ b/cmd/github-actions-runner-job/Dockerfile @@ -11,10 +11,17 @@ RUN apt-get update \ RUN set -eux; \ runner_arch="${TARGETARCH}"; \ if [ "$runner_arch" = "amd64" ]; then runner_arch="x64"; fi; \ + case "$runner_arch" in \ + x64) runner_sha256="18f8f68ed1892854ff2ab1bab4fcaa2f5abeedc98093b6cb13638991725cab74" ;; \ + arm64) runner_sha256="69ac7e5692f877189e7dddf4a1bb16cbbd6425568cd69a0359895fac48b9ad3b" ;; \ + *) echo "unsupported actions runner arch: $runner_arch" >&2; exit 1 ;; \ + esac; \ mkdir -p /opt/actions-runner; \ - curl -fsSL \ + curl --fail --show-error --location --retry 5 --retry-all-errors --retry-delay 2 --connect-timeout 15 \ "https://github.com/actions/runner/releases/download/v${ACTIONS_RUNNER_VERSION}/actions-runner-linux-${runner_arch}-${ACTIONS_RUNNER_VERSION}.tar.gz" \ -o /opt/actions-runner/actions-runner.tar.gz; \ + echo "${runner_sha256} /opt/actions-runner/actions-runner.tar.gz" | sha256sum -c -; \ + tar -tzf /opt/actions-runner/actions-runner.tar.gz ./config.sh ./run.sh >/dev/null; \ chmod 0644 /opt/actions-runner/actions-runner.tar.gz; \ useradd -m -s /bin/bash runner diff --git a/cmd/github-actions-runner-job/entrypoint.sh b/cmd/github-actions-runner-job/entrypoint.sh index d9158ef..2901df6 100644 --- a/cmd/github-actions-runner-job/entrypoint.sh +++ b/cmd/github-actions-runner-job/entrypoint.sh @@ -4,9 +4,14 @@ set -euo pipefail archive="${GITHUB_ACTIONS_RUNNER_ARCHIVE:-/opt/actions-runner/actions-runner.tar.gz}" runner_dir="${GITHUB_ACTIONS_RUNNER_DIR:-/home/runner/actions-runner}" +if [ ! -f "$archive" ]; then + echo "github-actions-runner-job: runner archive not found at $archive" >&2 + exit 1 +fi + if [ ! -x "$runner_dir/config.sh" ]; then mkdir -p "$runner_dir" - tar -xzf "$archive" -C "$runner_dir" + tar --no-same-owner -xzf "$archive" -C "$runner_dir" fi exec /usr/local/bin/github-actions-runner-job "$@" diff --git a/release_packaging_test.go b/release_packaging_test.go index e9bd676..58eea4a 100644 --- a/release_packaging_test.go +++ b/release_packaging_test.go @@ -102,7 +102,12 @@ func TestGitHubActionsRunnerJobImageCarriesCompressedRunnerArchive(t *testing.T) } for _, want := range []string{ "ARG ACTIONS_RUNNER_VERSION=", + "curl --fail --show-error --location --retry 5 --retry-all-errors --retry-delay 2 --connect-timeout 15", "actions-runner-linux-${runner_arch}-${ACTIONS_RUNNER_VERSION}.tar.gz", + `x64) runner_sha256="18f8f68ed1892854ff2ab1bab4fcaa2f5abeedc98093b6cb13638991725cab74"`, + `arm64) runner_sha256="69ac7e5692f877189e7dddf4a1bb16cbbd6425568cd69a0359895fac48b9ad3b"`, + `echo "${runner_sha256} /opt/actions-runner/actions-runner.tar.gz" | sha256sum -c -`, + "tar -tzf /opt/actions-runner/actions-runner.tar.gz ./config.sh ./run.sh >/dev/null", "GITHUB_ACTIONS_RUNNER_ARCHIVE=/opt/actions-runner/actions-runner.tar.gz", "GITHUB_ACTIONS_RUNNER_DIR=/home/runner/actions-runner", "COPY --chmod=0755 cmd/github-actions-runner-job/entrypoint.sh /usr/local/bin/github-actions-runner-job-entrypoint", @@ -121,7 +126,9 @@ func TestGitHubActionsRunnerJobImageCarriesCompressedRunnerArchive(t *testing.T) for _, want := range []string{ "${GITHUB_ACTIONS_RUNNER_ARCHIVE:-/opt/actions-runner/actions-runner.tar.gz}", "${GITHUB_ACTIONS_RUNNER_DIR:-/home/runner/actions-runner}", - `tar -xzf "$archive" -C "$runner_dir"`, + `[ ! -f "$archive" ]`, + "runner archive not found", + `tar --no-same-owner -xzf "$archive" -C "$runner_dir"`, `exec /usr/local/bin/github-actions-runner-job "$@"`, } { if !strings.Contains(entrypointText, want) {