From 3dcadefbfd05ffe6dad10b206909067950164ec1 Mon Sep 17 00:00:00 2001 From: "shoney.arickathil" Date: Tue, 25 Aug 2026 05:16:43 +0200 Subject: [PATCH] docs(releasing): why the release job stays on a hosted runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - self-hosted works technically: outbound HTTPS only, no inbound ports, honours HTTPS_PROXY/NO_PROXY — a box behind a proxy is fine - but it defeats the pinned-runner decision: the build host sets the glibc floor, so a workstation runner (2.39 here) puts it back to 2.38+ and drops Ubuntu 22.04 / Debian 12 / RHEL 9 - and a workstation-built release is unattested - records what self-hosting accepts: jobs run as the starting user, with that user's ~/.ssh, credentials and network reach — including hosts named in ~/.ssh/config; worst on public repos, where a stranger's PR runs code on the runner - if unavoidable: dedicated VM, unprivileged user, --ephemeral, segmented network, treat .credentials as a secret Co-Authored-By: Claude Opus 5 (1M context) --- docs/guides/releasing.md | 51 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/docs/guides/releasing.md b/docs/guides/releasing.md index 6ab209f..9f3c5cc 100644 --- a/docs/guides/releasing.md +++ b/docs/guides/releasing.md @@ -98,6 +98,57 @@ Known first-run risks, in the order they are likely to bite: runners, absent in slim containers); and a 403 on publish, which is step 4. +## Why the release job is NOT on a self-hosted runner + +A self-hosted runner would work — it needs no inbound ports, polls +GitHub over outbound HTTPS, and honours `HTTPS_PROXY`/`NO_PROXY`, so a +box behind a proxy is fine. Two reasons not to use one for THIS job: + +**It defeats the point of pinning the runner.** The release binaries +link glibc dynamically, so the build host sets the floor every user +must clear. `ubuntu-22.04` was chosen to keep that floor near 2.35. A +runner on a developer machine (glibc 2.39 here) puts it back at 2.38+ +and silently drops Ubuntu 22.04, Debian 12 and RHEL 9 — the exact +regression the pinned image prevents. If a self-hosted runner is +unavoidable, build inside a container pinned to the oldest glibc you +intend to support, not on the host. + +**A release built on a workstation is unattested.** "It built on my +machine" is what a pipeline exists to stop being true. + +### If you do self-host, what you are accepting + +A runner executes workflow code **as the user that started it**, with +that user's filesystem and network reach. On a personal workstation +that means `~/.ssh`, `~/.config/gh`, cloud and cluster credentials, +browser profiles, and every host reachable from it — including LAN +services and anything named in `~/.ssh/config`, which on a work laptop +is usually production. A job does not need to be malicious to leak; +it needs to be careless once. + +The risk is highest on a **public** repository, where a pull request +from a stranger can run arbitrary code on the runner. GitHub's own +guidance is not to use self-hosted runners with public repositories. +On a private repository the blast radius is smaller but not zero: +anyone with write access, or one compromised token, reaches the same +shell. + +If it is still the right call, make it boring: + +- a dedicated VM or container, never a workstation, on a network + segment that cannot reach production; +- a separate unprivileged user with no SSH keys, no cloud config, and + no credentials of its own; +- `--ephemeral` registration so each job gets a clean runner and a + poisoned toolchain cannot outlive one build; +- `.credentials` under the runner's home is a long-lived credential to + act as that runner — treat the box as holding a secret; +- restrict egress if the workload allows; the same outbound HTTPS the + runner needs is what exfiltration would use. + +A reasonable split: self-hosted for tests that need private-network +access or unusual hardware, GitHub-hosted for the release artifact. + ## Releasing from the pipeline ```