Skip to content
Latchkey

How to Secure a Self-Hosted Runner Against Public-Repo PRs in GitHub Actions

GitHub explicitly warns: do not use self-hosted runners on public repositories, because a fork PR can run arbitrary code on your machine.

Self-hosted runners are not sandboxed by default, so a malicious fork PR could execute on your host. Keep them on private repos, require approval for first-time contributors, and never use persistent runners for untrusted code.

Steps

  • Avoid self-hosted runners entirely on public repositories.
  • Set Actions to require approval for all outside collaborators.
  • Use ephemeral runners so one PR cannot poison the next job.
  • Restrict runners to selected repos with a runner group.

Require approval (org policy)

GitHub settings
# Settings to Actions to General to Fork pull request workflows
# from outside collaborators:
#   "Require approval for all external contributors"
# Also: do not enable self-hosted runners on the public repo.

Gotchas

  • A persistent runner keeps state between jobs; a compromised job can leave a backdoor for the next one. Ephemeral runners mitigate this.
  • GITHUB_TOKEN is read-only on pull_request from forks, but the runner host itself is still exposed if a fork job runs on it.
  • Managed runners (Latchkey) run each job on a fresh, isolated machine, which removes the persistent-host attack surface for private-repo CI.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →