---
title: "Self-hosted runner security"
description: "Use disposable job environments to reduce the risk from untrusted workflow code on a self-hosted GitHub runner."
url: "https://architecture.mnppi.org/operations/runner-security/"
status: "Pilot"
last_updated: "2026-07-23"
---

# Self-hosted runner security

**Standard details**

- Status: Pilot
- Reviewed: July 23, 2026
- Cadence: Review each quarter

The runner host is a trust boundary.
A workflow can read or change anything that its job environment can reach.

The preferred model keeps the host small and creates one isolated environment for each job.
The environment registers for one job and disappears after the job ends.

## Recommended model

Use a just-in-time GitHub runner inside a rootless container.
Just-in-time means GitHub registers the runner for one job only.

The environment should have:

- No host filesystem mounts.
- No container engine socket.
- No privileged mode.
- No added Linux capabilities.
- A `no-new-privileges` control.
- CPU, memory, process, and disk limits.
- An isolated working directory.
- A short registration lifetime.
- Automatic cleanup after success, failure, or timeout.

The host keeps the minimum scheduler and container runtime.
It does not keep project source or job credentials after cleanup.

## Isolation options

### Rootless container

This is the default for normal repository checks.
It is fast, repeatable, and practical for a small organization.
It shares the host kernel, so it is not a complete hostile-code boundary.

### Micro virtual machine

A micro virtual machine gives each job a separate kernel.
Use it for stronger isolation when the host can support the added complexity.

### Ephemeral virtual machine

A new virtual machine gives the strongest common separation.
It costs more time and operating work.
Use it for high-risk or untrusted workloads.

### Cloud-hosted runner

A GitHub-hosted runner removes the long-lived private host.
Use it when repository policy permits the change.
Do not switch only to avoid a queued designated runner.

## Job admission

Run untrusted fork code without secrets.
Do not use privileged workflow events to execute untrusted pull request code.

Limit GitHub token permissions for each job.
Keep package and cloud credentials out of validation jobs unless the check requires them.

## Cleanup gate

A job is complete only when:

- GitHub removes the one-job registration.
- The isolated environment stops.
- The work directory disappears.
- Temporary credentials expire or are removed.
- No project process remains on the host.

> **Caution**
>
> Disposable containers reduce persistence risk.
> They do not make a shared kernel safe for every hostile workload.
