Preventing a malicious pull request from compromising your cloud network when using public self-hosted runners requires
- strict network isolation,
- ephemeral compute instances and
- mandatory manual workflow approvals.
Avoid running persistent self-hosted runners directly on public repositories if possible. [1]
Network and Infrastructure Isolation
Zero internal access:
Place runners in a dedicated, firewalled Virtual Private Cloud (VPC) with zero routing or peering to your corporate network, production environments, or internal databases. [1, 2, 3, 4]
Strict egress filtering:
Block all outbound traffic by default, allowing only explicit outbound ports/IPs required for package downloads or reporting back to the CI provider. [5, 6]
Restrict internet access. Use a NAT Gateway or firewall to whitelist only required package registries (e.g., npm, PyPI) and GitHub IPs
Network micro-segmentation:
Place runners in an isolated VPC subnet. Block all internal traffic to other cloud services using security groups or network policies.
Ephemeral architecture:
Spin up clean runner instances (such as short-lived container instances or VMs) for a single job and automatically destroy them immediately after completion. [1, 7]
Deploy tools like Actions Runner Controller (ARC) on Kubernetes or ephemeral cloud VMs. They spin up for one job and destroy themselves immediately
Disable host access:
Run the actions runner inside an unprivileged container. Never map the host’s Docker socket (
/var/run/docker.sock) into the runner container
Access Control and Configuration
Require manual approval:
Configure repository settings to require explicit manual approval for any workflow triggered by first-time contributors or external fork pull requests. [1, 5]
Set Repository Settings > Actions > General to require approval for all outside contributors
Least privilege tokens:
Enforce read-only default permissions for the orchestrator token (
GITHUB_TOKEN) and avoid exposing long-lived cloud credentials or secrets to public fork builds. [3, 8, 9]Change the default
GITHUB_TOKENpermissions to Read-only under the workflow settings
No root execution:
Ensure runner daemon processes and container tasks never run with
rootorsudoprivileges on the host machine. [7, 10]Bind sensitive deployment targets to a GitHub Environment that mandates a manual review before execution.