Security

Last updated 5 September 2026

onctl runs each GitHub Actions job in its own Firecracker microVM on dedicated hosts in Falkenstein, Germany. This page is the honest version of that story — what is built, what is not, and how to reach us. It is sourced from the internal security notes in the controller repo.

Can another customer see my workload?

No, at the VM and data layers we operate. Every job gets its own microVM. An ebtables rule on the host bridge drops all VM-to-VM traffic, so two runners on the same box cannot talk to each other — including two of yours. Job records, usage, and the dashboard API are scoped by GitHub App installation_id. There is no cross-tenant query path.

We use one GitHub App for all customers, the standard multi-tenant App model: each installation gets its own short-lived GitHub token. We do not issue a dedicated App per customer.

What survives after my job?

The microVM is destroyed when GitHub reports the job completed, and by watchdogs if the runner never registers (5 minutes) or the job never finishes (6 hours). Those watches are restored if the controller restarts, so a deploy does not leave a billing VM behind.

What we keep: job metadata (repo name, job id, profile, timestamps, duration) and usage rows used for the monthly minute cap and billing. There is no retention TTL today — rows stay until you ask us to delete them. We do not keep your repository source; checkout happens inside the ephemeral VM using GitHub's job token.

Who can access my secrets?

Workflow secrets stay in GitHub's job context. We never see them. The only runner credential we handle is a one-time JIT config from GitHub, passed into the VM as a process argument. Our bootstrap script does not write it to a dedicated file. The GitHub runner binary may persist config internally; we have not audited that binary. The credential dies when the VM disk is destroyed.

The GitHub App needs repository Administration (to register ephemeral runners) and workflow_job webhooks. It does not clone your repo on our control plane.

Where does my workload execute?

Firecracker microVMs on dedicated hosts in Falkenstein, Germany (EU). There is no US region today. The control plane is a separate Hetzner VM; job state lives in hosted Postgres (Supabase).

What data does onctl retain?

GitHub user identity (OAuth), App installation id, connected repo names, job metadata, and vCPU-weighted usage duration. Controller logs go to Loki on the control-plane VM. We do not currently scrub secrets from those logs, and we do not auto-delete old rows. Email hello@onctl.io to request deletion.

What we cap, and what we don't

Each installation is limited to 4 simultaneous runners and 500 vCPU-minutes per UTC calendar month. Past that ceiling, new VMs are refused and jobs stay queued. We do not have customer-configured spend caps, Slack billing alerts, or crypto-mining pattern detection.

Report a vulnerability

Email hello@onctl.io with enough detail to reproduce. This is a small beta; we read every message. Please don't file security issues on a public tracker.