Skip to content

SEC010 — self-hosted-fork-runner

Severity: warning · Category: Security

What it checks

Flags a job whose runs-on: doesn't match a known GitHub-hosted label (ubuntu-*, windows-*, macos-*) or a known third-party managed runner service (depot-*, buildjet-*, warp-*, codspeed*, namespace-*, blacksmith-*, ubicloud-*), in a workflow that also triggers on pull_request.

Why it matters

GitHub-hosted runners are ephemeral, clean virtual machines — a compromised job can't persist anything or affect the next run. A genuinely self-hosted runner has no such guarantee: if it also accepts pull_request, anyone who can open a PR (which, on a public repo, is anyone with a GitHub account) can run code on it, potentially compromising the underlying machine or anything else it has network access to. Third-party managed runner services (Depot, CodSpeed, and similar) sit closer to GitHub-hosted on this spectrum — they provision fresh, provider-managed VMs per job — so they're excluded from this check rather than treated as equivalent risk to a repo owner's own hardware.

Examples

Flagged — a custom runner label, with no indication of what backs it:

on: pull_request

jobs:
  build:
    runs-on: my-office-mac-mini
    steps:
      - run: make build

Fixed — use a GitHub-hosted or known managed-service runner for anything a fork PR can trigger:

on: pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: make build

If a genuinely self-hosted runner is required (specialized hardware, an internal network dependency), keep it off pull_request entirely, or require manual approval and use ephemeral, just-in-time runner registration.

Suppressing

The finding is reported on the job's declaration line:

  build: # vlotpipe: ignore[SEC010]
    runs-on: my-office-mac-mini

Reasonable if manual-approval gating or ephemeral runner registration is already in place and the risk has been consciously accepted.