Hardened mirror of GitHub's Actions Runner
image (ghcr.io/actions/actions-runner),
with postgresql-client added for self-hosted CI jobs that talk to Postgres.
THEKROLL's internal runner image, published publicly as a reference build.
Unofficial. Not affiliated with, sponsored by, or endorsed by GitHub. "GitHub" and "GitHub Actions" are trademarks of GitHub, Inc. See
NOTICE.md.
This is a rebase, not a source build. We pull GitHub's pinned, prebuilt runner image and add one thin layer on top:
ARG RUNNER_VERSION
FROM ghcr.io/actions/actions-runner:${RUNNER_VERSION}
USER root
RUN apt-get install -y --no-install-recommends postgresql-client
USER runnerWe do not rebuild the runner from source, and we do not re-derive its base. The value this repo adds is the nightly security gate around that rebase, not the build itself.
A single GitHub Actions workflow (.github/workflows/mirror-build.yml):
Build & gate — nightly, on every push to main, and on manual dispatch:
- Resolve the latest
actions/runnerrelease. Build if it's newer than the last one we built — or always, when triggered manually or by a push (so adding a tool to theDockerfilerebuilds without waiting for a release). - Build the rebased image (
FROMthe pinned upstream release, add the extra tooling). The apt layer cache is busted once per UTC day so Ubuntu security updates land even when nothing else changed. - Trivy-scan the image. Push only if there are no CRITICAL/HIGH vulnerabilities with an available fix.
- On clean: push
:tag,:latest, and@sha256:…; writeimage-pin.yml(recording both our digest and the upstream image digest we rebased); open a digest-pin PR. Merging the PR is the rollout gate. - On findings: file/update a per-version CVE issue, retain the full audit bundle (SARIF + SBOM) for 90 days, and do not push.
Rescan — nightly only:
- Re-scan the already-published image against today's Trivy database to catch CVEs disclosed after the build. Information only — never rebuilds or pushes. Files an issue if new findings appear; resolves it when they clear.
ghcr.io/thekroll-ltd/actions-runner:<version> and
ghcr.io/thekroll-ltd/actions-runner@sha256:<digest>.
- Version tags track upstream runner releases, without the
v— upstream tags releasesv2.335.1, the image registry tags them2.335.1, and so do we. The digest inimage-pin.ymlis the authoritative pin. - linux/amd64 only.
- Drop-in for
ghcr.io/actions/actions-runner: samerunneruser (UID 1001), same/home/runnerworkdir, noENTRYPOINT(ARC / the runner start script provides it), pluspsqlonPATH.
Point your RunnerScaleSet / runner image at the pinned digest from
image-pin.yml, e.g.:
template:
spec:
containers:
- name: runner
image: ghcr.io/thekroll-ltd/actions-runner@sha256:<digest>Edit the RUN apt-get install list in the Dockerfile, commit to main. The
push triggers a rebuild + scan of the current upstream release; if clean, a new
digest-pin PR opens. Keep additions to --no-install-recommends and prefer
client tools over services to keep the image lean and the CVE surface small.
- Severity policy:
CRITICAL,HIGH,--ignore-unfixed(only vulnerabilities with an available fix block — you can't act on what has no patch yet). - Findings are reported to the Security tab (SARIF categories
trivy-imagefor build-time,trivy-rescanfor post-release) and tracked as one GitHub issue per version across both build and rescan. - Accepted findings go in
.trivyignore, one CVE per line, with a comment explaining why and a revisit date — the file's git history is the audit trail.
- Build system (this repo): Apache-2.0 (
LICENSE). - Image: redistributes the MIT-licensed runner on its Ubuntu/.NET base,
plus permissive
postgresql-client(PostgreSQL License). No copyleft obligation on the application layer. Full breakdown and the trademark caveat inNOTICE.md.
Internal build, public as reference. No support, no compatibility guarantee.