Prerequisites
- Target system, dependencies and environment configured.
Usage
Purpose
CI/CD runners are the machines that execute pipeline jobs — and they run whatever the pipeline tells them to, often with access to secrets and networks. Self-hosted runners especially can become a foothold: they persist state between jobs, may run untrusted PR code, and sit inside your network. This skill covers securing runners so a malicious or compromised job can't turn the runner into a persistent attack platform, closing a frequently-overlooked gap in pipeline security.
When to use it
Securing any CI/CD setup, with particular urgency for self-hosted runners (cloud-hosted/ephemeral runners from the provider are more isolated by default). It complements pipeline hardening — the pipeline decides what runs; the runner is where it runs.
Procedure
- Prefer ephemeral runners — the key mitigation. A runner that's created fresh for each job and destroyed after leaves no persistent state for an attacker to establish a foothold in. Ephemeral (single-use) runners are the strongest defence against runner compromise; if a job is malicious, it gets a clean throwaway machine. Prefer them over long-lived persistent runners.
- Isolate runners from sensitive networks and resources. A runner sits somewhere with network access; a self-hosted runner on your internal network is a pivot point if compromised. Place runners in an isolated network segment with least-privilege access, not on the corporate LAN with reach to sensitive systems.
- Don't run untrusted code on privileged runners — critical for self-hosted. The classic self-hosted-runner attack: a malicious PR from a fork runs on your self-hosted runner (which has your secrets/network), executing the attacker's code in your environment. Never run untrusted PR code on runners with access to secrets or sensitive networks; require approval for fork-PR workflows, or use isolated ephemeral runners for untrusted builds.
- Least-privilege the runner's access. Scope what secrets and resources the runner can reach to the minimum the jobs need. A runner with broad access turns any job compromise into broad compromise (the pipeline least-privilege principle, at the runner).
- Clean state between jobs. On persistent runners, jobs can leave behind (or read) data from other jobs — secrets in memory/disk, cached credentials, malware. Clean the workspace and environment between jobs, or (better) use ephemeral runners that start clean every time.
- Keep runners patched and hardened like any host (the Linux/Windows hardening domains) — they're machines that run code and are a target.
- Monitor runner activity. Log what runs on runners and alert on anomalies (a job accessing unexpected resources, unusual network connections) — a compromised runner is a serious foothold worth detecting.
Cheatsheet
runners = machines that RUN pipeline jobs (with secrets/network access)
self-hosted especially = a foothold (persist state, run untrusted code, inside your net)
1. EPHEMERAL runners (the key mitigation): fresh per job, destroyed after
-> no persistent state for a foothold ; malicious job gets a throwaway machine
2. ISOLATE from sensitive networks (self-hosted on corporate LAN = pivot point)
-> isolated segment, least-privilege access
3. DON'T run untrusted code on privileged runners (critical, self-hosted)
classic attack: malicious fork-PR runs on your runner w/ your secrets/network
-> require approval for fork PRs / isolated ephemeral runners for untrusted builds
4. LEAST-PRIVILEGE runner access (broad access = job compromise -> broad compromise)
5. CLEAN state between jobs (persistent runners leak secrets/data across jobs) — or go ephemeral
6. PATCH + harden runners (they're hosts + targets)
7. MONITOR runner activity (compromised runner = serious foothold)
Reading the setup
- Persistent self-hosted runners running untrusted fork-PR code with secret/network access = the classic, dangerous self-hosted-runner attack; an attacker's PR executes in your environment with your secrets. The highest-priority runner risk to close. Use ephemeral runners or require approval for untrusted builds.
- Long-lived persistent runners = state accumulates and can be a foothold; ephemeral single-use runners eliminate the persistent-foothold risk. The key mitigation.
- A self-hosted runner on the corporate LAN = a pivot point into your internal network if compromised; isolate runners in a segmented network with least-privilege reach.
- Runners with broad secret/resource access = any job compromise becomes broad compromise; scope runner access to the minimum.
- Persistent runners not cleaned between jobs = one job can read another's secrets or leave malware for the next; clean state, or use ephemeral runners that start fresh.
- Ephemeral, isolated, least-privileged, monitored runners with untrusted builds separated = runners that can't become a persistent attack platform.
The fix / best practice
- Use ephemeral (single-use) runners wherever possible — the strongest defence, leaving no persistent foothold.
- Isolate runners in a segmented network with least-privilege access to secrets and resources.
- Never run untrusted code (fork PRs) on privileged runners — require approval or route untrusted builds to isolated ephemeral runners without secrets.
- Clean state between jobs on any persistent runner.
- Patch and harden runners as hosts, and monitor their activity for anomalies.
- Combine with pipeline hardening (least-privilege jobs, no secrets to fork PRs).
Pitfalls
- Running untrusted fork-PR code on privileged self-hosted runners. The classic attack — the attacker's code runs with your secrets and network access. Never do it; isolate untrusted builds.
- Long-lived persistent runners. They accumulate state that becomes a foothold; ephemeral single-use runners are far safer. Prefer them.
- Runners on sensitive networks. A self-hosted runner on the corporate LAN is a pivot point if compromised; isolate it.
- Broad runner access. A runner that can reach many secrets/resources turns any job compromise into broad compromise; least-privilege it.
- Not cleaning state. Persistent runners leak secrets and data across jobs; clean between jobs or go ephemeral.
- Treating runners as invisible infrastructure. They run code and are a target; patch, harden, and monitor them.
References
- GitHub Actions and GitLab CI self-hosted runner security documentation
- The pipeline-hardening skill and the Linux/Windows hardening domains
- OWASP CI/CD Security Top 10 (runner/execution risks)
- Poisoned pipeline execution research
Inputs
- Relevant source code, logs, network traces, or system specifications.
Outputs
- Analysis findings, security audit report, or generated code artifacts.
1---2name: secure-runners3description: Use when securing CI/CD build runners — especially self-hosted ones that persist state and run untrusted code, closing a common foothold into the build environment.4---5678## Prerequisites9- Target system, dependencies and environment configured.1011## Usage12### Purpose1314CI/CD runners are the machines that execute pipeline jobs — and they run whatever the pipeline tells them to, often with access to secrets and networks. Self-hosted runners especially can become a foothold: they persist state between jobs, may run untrusted PR code, and sit inside your network. This skill covers securing runners so a malicious or compromised job can't turn the runner into a persistent attack platform, closing a frequently-overlooked gap in pipeline security.1516### When to use it1718Securing any CI/CD setup, with particular urgency for self-hosted runners (cloud-hosted/ephemeral runners from the provider are more isolated by default). It complements pipeline hardening — the pipeline decides what runs; the runner is where it runs.1920### Procedure21221. **Prefer ephemeral runners — the key mitigation.** A runner that's created fresh for each job and destroyed after leaves no persistent state for an attacker to establish a foothold in. Ephemeral (single-use) runners are the strongest defence against runner compromise; if a job is malicious, it gets a clean throwaway machine. Prefer them over long-lived persistent runners.232. **Isolate runners from sensitive networks and resources.** A runner sits somewhere with network access; a self-hosted runner on your internal network is a pivot point if compromised. Place runners in an isolated network segment with least-privilege access, not on the corporate LAN with reach to sensitive systems.243. **Don't run untrusted code on privileged runners — critical for self-hosted.** The classic self-hosted-runner attack: a malicious PR from a fork runs on your self-hosted runner (which has your secrets/network), executing the attacker's code in your environment. Never run untrusted PR code on runners with access to secrets or sensitive networks; require approval for fork-PR workflows, or use isolated ephemeral runners for untrusted builds.254. **Least-privilege the runner's access.** Scope what secrets and resources the runner can reach to the minimum the jobs need. A runner with broad access turns any job compromise into broad compromise (the pipeline least-privilege principle, at the runner).265. **Clean state between jobs.** On persistent runners, jobs can leave behind (or read) data from other jobs — secrets in memory/disk, cached credentials, malware. Clean the workspace and environment between jobs, or (better) use ephemeral runners that start clean every time.276. **Keep runners patched and hardened** like any host (the Linux/Windows hardening domains) — they're machines that run code and are a target.287. **Monitor runner activity.** Log what runs on runners and alert on anomalies (a job accessing unexpected resources, unusual network connections) — a compromised runner is a serious foothold worth detecting.2930### Cheatsheet3132```33runners = machines that RUN pipeline jobs (with secrets/network access)34 self-hosted especially = a foothold (persist state, run untrusted code, inside your net)35361. EPHEMERAL runners (the key mitigation): fresh per job, destroyed after37 -> no persistent state for a foothold ; malicious job gets a throwaway machine382. ISOLATE from sensitive networks (self-hosted on corporate LAN = pivot point)39 -> isolated segment, least-privilege access403. DON'T run untrusted code on privileged runners (critical, self-hosted)41 classic attack: malicious fork-PR runs on your runner w/ your secrets/network42 -> require approval for fork PRs / isolated ephemeral runners for untrusted builds434. LEAST-PRIVILEGE runner access (broad access = job compromise -> broad compromise)445. CLEAN state between jobs (persistent runners leak secrets/data across jobs) — or go ephemeral456. PATCH + harden runners (they're hosts + targets)467. MONITOR runner activity (compromised runner = serious foothold)47```4849### Reading the setup5051- **Persistent self-hosted runners running untrusted fork-PR code with secret/network access** = the classic, dangerous self-hosted-runner attack; an attacker's PR executes in your environment with your secrets. The highest-priority runner risk to close. Use ephemeral runners or require approval for untrusted builds.52- **Long-lived persistent runners** = state accumulates and can be a foothold; ephemeral single-use runners eliminate the persistent-foothold risk. The key mitigation.53- **A self-hosted runner on the corporate LAN** = a pivot point into your internal network if compromised; isolate runners in a segmented network with least-privilege reach.54- **Runners with broad secret/resource access** = any job compromise becomes broad compromise; scope runner access to the minimum.55- **Persistent runners not cleaned between jobs** = one job can read another's secrets or leave malware for the next; clean state, or use ephemeral runners that start fresh.56- **Ephemeral, isolated, least-privileged, monitored runners with untrusted builds separated** = runners that can't become a persistent attack platform.5758### The fix / best practice5960- **Use ephemeral (single-use) runners** wherever possible — the strongest defence, leaving no persistent foothold.61- **Isolate runners** in a segmented network with least-privilege access to secrets and resources.62- **Never run untrusted code (fork PRs) on privileged runners** — require approval or route untrusted builds to isolated ephemeral runners without secrets.63- **Clean state between jobs** on any persistent runner.64- **Patch and harden runners** as hosts, and **monitor** their activity for anomalies.65- Combine with pipeline hardening (least-privilege jobs, no secrets to fork PRs).6667### Pitfalls6869- **Running untrusted fork-PR code on privileged self-hosted runners.** The classic attack — the attacker's code runs with your secrets and network access. Never do it; isolate untrusted builds.70- **Long-lived persistent runners.** They accumulate state that becomes a foothold; ephemeral single-use runners are far safer. Prefer them.71- **Runners on sensitive networks.** A self-hosted runner on the corporate LAN is a pivot point if compromised; isolate it.72- **Broad runner access.** A runner that can reach many secrets/resources turns any job compromise into broad compromise; least-privilege it.73- **Not cleaning state.** Persistent runners leak secrets and data across jobs; clean between jobs or go ephemeral.74- **Treating runners as invisible infrastructure.** They run code and are a target; patch, harden, and monitor them.7576### References7778- GitHub Actions and GitLab CI self-hosted runner security documentation79- The pipeline-hardening skill and the Linux/Windows hardening domains80- OWASP CI/CD Security Top 10 (runner/execution risks)81- Poisoned pipeline execution research8283## Inputs84- Relevant source code, logs, network traces, or system specifications.8586## Outputs87- Analysis findings, security audit report, or generated code artifacts.