Skip to content

Security & isolation

Where and how your code runs — made verifiable.

Your CI runs on our infrastructure, and every job runs in its own hardware-virtualized micro-VM. This page describes exactly how that isolation works, how long a job’s environment lives, and how you can independently verify the image your code runs on — without a sales call or an NDA.

Last updated: 2026-09-27 · v1.6

The isolation model

Untrusted CI code — your build steps, and anything they spawn, including Docker-in-Docker — is contained by several independent layers. The micro-VM is the primary boundary; the other layers limit what a job can reach and make an attempted breakout visible. This is defense-in-depth, not “trust the container.”

LayerMechanismWhat it contains
Hardware-virtualized micro-VMEach runner pod runs inside its own micro-VM with its own guest kernel, using Kata Containers. A micro-VM is a lightweight virtual machine — not a shared-kernel container.The primary boundary. CI code — and its Docker-in-Docker — cannot reach the host kernel or any other job’s VM.
Network default-denyThe runner’s network is deny-by-default, enforced in the kernel with eBPF / Cilium. It cannot accept inbound connections or reach into the cluster: private IP ranges, the cloud-metadata endpoint, the control plane, and neighbouring pods are all blocked, except an internal pull-through cache for packages and images. Outbound reaches the public internet.Lateral movement, cloud-metadata credential theft, and reaching internal services.
No cluster credentialsThe runner holds no token to the orchestrator (Kubernetes API).The foothold for privilege escalation — even with root inside the VM, there is no cluster credential to pivot with.
Workload privilegesAs on GitHub-hosted runners, your job runs as the non-root runner user with passwordless sudo, so it has full root inside its own micro-VM — as does the Docker-in-Docker engine. That privilege ends at the VM boundary: no host devices, host namespaces or host mounts, and no cluster credentials.Keeps root inside the job’s own VM, away from the host.
Node separationRunners run on dedicated runner hosts, physically separate from the control plane, secrets, and platform data.Blast radius: a compromised job is nowhere near the platform’s control plane or other tenants’ data.
Runtime threat detectionHosts run eBPF / Tetragon runtime detection, watching for activity that would indicate an escape from a VM onto the host.Turns an attempted breakout into an observable, recorded event rather than a silent one.

We name the primitives and say what each is for; we do not publish the policies, allowlists, versions, or topology behind them. Components are kept current on a security floor — specific version numbers are deliberately not published, since a version maps to a known set of CVEs.

Ephemeral by design

A job’s environment does not outlive the job.

The boundary of a job is the boundary of trust.

Supply chain you can verify

The image your code runs on is built in public CI and is independently verifiable — you don’t have to take our word for what’s inside it.

SLSA build provenance OpenSSF Scorecard Signed with cosign License Apache-2.0

The badges link to the live attestations and Scorecard; the signature, provenance and SBOM are verifiable with the commands below.

Immutable images. Digests are immutable; tags are pointers: vYYYYMMDD and sha-<commit> can be re-pointed by a rebuild, and untagged digests are cleaned up over time — so pin vYYYYMMDD@sha256:. On our side, the runner fleet is pinned to an exact digest, and its signature and provenance are verified before each re-pin.

Every image built from main is signed with cosign keyless (Sigstore — Fulcio + Rekor, via GitHub Actions OIDC) and carries SLSA build provenance and a CycloneDX SBOM attestation. The signature is applied only after the published-by-digest artifact passes a trivy gate that blocks fixable HIGH/CRITICAL vulnerabilities in OS packages — so a valid signature also means the image passed the CVE gate. The image is rebuilt weekly with fresh apt patches; Renovate bumps the base and tools; runners move to a new digest after its signature is verified.

Image: ghcr.io/tempusbuild/runner-ubuntu-24.04 — date tags, no floating :latest. To see which image a job ran on, open Set up job → Runner Image → Version: vYYYYMMDD in its log. Work against the @sha256: digest, not a tag:

IMAGE=ghcr.io/tempusbuild/runner-ubuntu-24.04
DIGEST=$(docker buildx imagetools inspect "${IMAGE}:vYYYYMMDD" --format '{{.Manifest.Digest}}')

1. Signature — binds the image to our build workflow and to GitHub’s OIDC issuer. Any other identity is not our build:

cosign verify \
  --certificate-identity-regexp '^https://github\.com/tempusbuild/runner-images/\.github/workflows/build\.yml@refs/heads/main$' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  "${IMAGE}@${DIGEST}"

2. Build provenance — a Sigstore-signed SLSA attestation, verified with the gh CLI:

gh attestation verify "oci://${IMAGE}@${DIGEST}" --owner tempusbuild

3. SBOM (CycloneDX) — a cosign attestation on the same digest. The SBOM is too large for the transparency log, so it is TSA-timestamped (RFC3161) instead of logged to Rekor; verification therefore skips the Rekor lookup but still checks identity, signature, and the trusted timestamp:

cosign verify-attestation \
  --type cyclonedx \
  --insecure-ignore-tlog \
  --use-signed-timestamps \
  --certificate-identity-regexp '^https://github\.com/tempusbuild/runner-images/\.github/workflows/build\.yml@refs/heads/main$' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  "${IMAGE}@${DIGEST}"

--insecure-ignore-tlog waives only the Rekor lookup; the signature, the signing identity, and the RFC3161 timestamp are still verified. The signature in step 1 is the cryptographic anchor; provenance and SBOM bind to the same digest.

The signature and provenance are recorded in the public Rekor transparency log (открывается в новой вкладке). The full walkthrough and our CVE policy (открывается в новой вкладке) are in the runner-images SECURITY.md; the build workflow (открывается в новой вкладке) and the whole repository are open at github.com/tempusbuild/runner-images (открывается в новой вкладке).

Data & tenancy

Compliance & assessments

We state what exists today and what is on the roadmap — and nothing we haven’t earned.

Available now

On the roadmap

We are not currently certified against SOC 2 or any equivalent. The claims on this page are the ones you can verify directly today. Assessment reports, once available, are shared under NDA:

Request a security report — there is no lead-capture form on this page.

Responsible disclosure

Found a vulnerability in the platform, the runner images, or the supply-chain pipeline? Report it responsibly:

Please don’t open a public issue for an unpatched vulnerability. We acknowledge receipt and keep you posted through triage and fix.

Subprocessors

We use a small number of third-party processors to run the service. Personal data is processed only as needed to deliver it.

SubprocessorPurposeLocation
HetznerCompute and backupsEU
GitHubSource, identity (OAuth / GitHub App), CI secret deliveryUS
MailgunTransactional email and notificationsEU
DodoPaymentsPayment processing (merchant of record)US
GoogleWebsite analytics (Google Analytics): cookieless aggregated signals before your choice; cookies only with consentUS
YandexWebsite analytics (Yandex Metrica), only with your consentRU
SentryError monitoring: error traces with GitHub id/login; no email or IPEU (Germany)
OpenRouter (→ Anthropic)LLM inference for the cost advisor (enabled for all accounts) — receives aggregated cost metrics, repository/workflow names and the text of any question you ask; no source code, secrets or user identitiesUS

This list is versioned; material changes are reflected here with the revision date above.