Self-hosted CI/CD runners give you more control over the build environment — more compute, custom tooling, access to internal networks — but that control comes with security responsibilities that cloud-hosted runners handle for you by default.
The core difference from cloud-hosted runners
Cloud-hosted runners (like GitHub-hosted Actions runners) are ephemeral and isolated — a fresh, clean environment spins up for each job and is destroyed afterward. Self-hosted runners are typically persistent machines you manage, which means anything a job does — installing something, leaving files behind, accessing the local network — can affect the next job that runs on the same machine, or worse, provide a foothold into your internal infrastructure.
The fork pull request risk
If a self-hosted runner is configured to run workflows triggered by pull requests from public forks, an external contributor's PR can execute arbitrary code on infrastructure that likely has access to your internal network. This is one of the most severe self-hosted runner misconfigurations, and it's disabled by default on GitHub for this exact reason — don't re-enable it without heavy sandboxing.
Isolate runners per trust level
Don't run jobs from public/external-facing repositories on the same runner pool as jobs from private, sensitive repositories. A compromise via one shouldn't grant a path to the other.
Treat runners as ephemeral where possible
Where feasible, provision self-hosted runners as ephemeral (spun up fresh per job, destroyed after) rather than long-lived persistent machines. This closes the gap where one job's leftover state or credentials could affect a later job.
Network segmentation
Self-hosted runners often live inside your internal network by design (to reach internal resources during builds). Segment them so a compromised runner can't freely reach production databases, internal admin tools, or other sensitive internal services beyond what the build genuinely needs.
Patch the runner host itself
The runner machine's OS and installed tooling need the same patching discipline as any other production-adjacent host — it's easy to treat CI infrastructure as lower priority than customer-facing systems, but a compromised runner can be a direct path into your broader environment.
Self-hosted runners aren't inherently unsafe — they're unsafe when treated like disposable cloud runners without the isolation cloud runners provide by default.