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-07-24 · v1.1

The isolation model

No single layer is the boundary. Untrusted CI code — your build steps, and anything they spawn, including Docker-in-Docker — is contained by several independent layers. If one is bypassed, the next still holds. 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 if a container is escaped, there is no cluster credential to pivot with.
Workload hardeningInside the VM, the job container runs with all Linux capabilities dropped, privilege escalation disabled (no-new-privileges), and a seccomp profile. The one privileged component is the Docker-in-Docker engine — required to build images — and its privilege exists only inside the micro-VM, never on the host (see Layer 1).Narrows what the job can do even before the VM boundary.
Node separationRunners run on dedicated nodes, 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 runtime detection with eBPF / Tetragon for container-escape and privilege-escalation attempts.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 Level 3 OpenSSF Scorecard Signed with cosign License Apache-2.0

Each badge links to its live record — the signature, provenance and SBOM are verifiable with the commands below.

Immutable images. Runner images are pinned by content digest (@sha256:), never a floating tag — the exact image you verified is the one that runs.

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 a green trivy HIGH/CRITICAL CVE scan of the published-by-digest artifact — so a valid signature also means the image passed the CVE gate.

Image: ghcr.io/tempusbuild/runner-ubuntu-24.04 — immutable digest tags, no floating :latest. 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
Dodo PaymentsPayment processing (merchant of record)US
OpenRouterLLM inference for the optional Advisor feature — receives aggregated cost metrics and structural labels (e.g. repository and workflow names); no source code, no secrets, and the acting user is pseudonymized (hashed)US

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