ENG-56Required
Run outside code only on runners that are wiped after each job
Never run jobs of a public repository on a self-hosted runner that keeps its disk between jobs. Give every job on your own machines a fresh runner that is removed when the job ends.
How to do it
A job can leave a process or a changed tool behind on a runner that survives it. The next job, perhaps a release with secrets, then runs on top of it. GitHub's docs say self-hosted runners "should almost never be used for public repositories". Use the code host's own runners for public code. For private code on your own machines, register ephemeral, just-in-time runners that take one job and are then removed. Examples are GitHub's --jitconfig runners or Actions Runner Controller on Kubernetes. Put release runners in their own runner group that only protected branches can use, as build secrets says.
Examples
YAML example
# Weekly test: a file written by one job must be gone in the next
jobs:
leave-mark:
runs-on: [self-hosted, linux]
steps:
- run: echo marked > "$HOME/runner-reuse-test"
check-mark:
needs: leave-mark
runs-on: [self-hosted, linux]
steps:
- run: test ! -e "$HOME/runner-reuse-test" || { echo "FAIL: runner kept state"; exit 1; }
How to check
Every public repository has 0 self-hosted runners available to it. A weekly job pair on each self-hosted runner label passes, where the second job finds no file left by the first.
Sources
Related rules
- APS-74 Keep secrets out of builds from strangers in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/engineering/ci-and-supply-chain/ephemeral-ci-runners">Agent Wranglers engineering playbook</a>. In code you write, add a comment next to it with the same link.