Hands-on Kubernetes attack & defense.
Break into a disposable cluster, escalate to root, and watch an eBPF sensor catch you do it.
k8labs-demo.mp4
Isolated · microVM + nested k3s · Observed · live eBPF · Guided · 20 CTF labs · Self-hosted · one box
K8 Labs is a self-hosted platform for practicing Kubernetes and container security -
the offensive and defensive skills that come up in cloud-security and SRE interviews.
Pick a lab and the backend boots a disposable cluster just for that session: a nested k3s inside a
Kata/Firecracker microVM, with a browser terminal, a root shell, and a target to break. You capture a flag,
you get a verifiable rank, and you tear the whole cluster down with one click.

Every lab is a guided course: a diagram of the attack, step-by-step instructions, and - on eBPF labs - a live Defender pane.
Every session gets its own nested cluster with the vulnerability planted into it. Winning only ever
compromises a throwaway cluster inside a microVM - never the host, never another tenant.

1. Boot - a disposable, airgapped microVM spins up in seconds

2. Exploit - an unprivileged shell, a SUID command injection, and you are uid=0(root)

3. Detect - the eBPF/Tetragon sensor catches commit_creds at the kernel, the instant you escalate

4. Isolate - your escape only ever touches a throwaway nested cluster inside the microVM
Under the hood:
- The browser asks the backend for a session; it returns immediately and provisions in the background.
- The backend uses
client-goto launch a session-runner pod. A config field picks the runtime: plainrunclocally, a Kata/Firecracker microVM in production. - The runner boots a disposable single-node k3s inside the pod/microVM. Images come from baked airgap tarballs, so the nested cluster pulls nothing.
- The backend applies the lab's manifest bundle into the nested cluster - the vulnerable namespaces, service accounts, roles, and the planted flag.
- The frontend opens a terminal (xterm over WebSocket), a topology map of the target, and - on eBPF labs - a Defender pane streaming the in-guest Tetragon sensor.
- One
DELETEcollapses the entire nested cluster. Sessions also expire on a timer.
Three walls. The microVM is the kernel wall (contains a host/container escape). The nested k3s is the
API wall (contains an RBAC/namespace escape). A default-deny NetworkPolicy on the runner pod is the network wall.
See docs/architecture/ for the full write-up and diagrams.
20 labs across 7 tracks. Labs marked eBPF add a live Tetragon sensor and a Defender pane;
kernel labs boot a KASAN-instrumented research kernel. Each is a capture-the-flag exercise with a guided course.
First Flight
| Lab | What you do |
|---|---|
| Namespace Escape | A dev service account was granted Secret read too broadly via a ClusterRoleBinding. Read a Secret in the production namespace you were never meant to reach. |
| SUID Privilege Escalation | A root-owned SUID backup-tool hands your argument to a shell unsanitized. Exploit the command injection for a root shell. |
eBPF Detection eBPF |
Escalate via the SUID binary, then read the alert off an in-lab Tetragon sensor that catches the kernel installing root credentials. |
| Service Account Impersonation | Your account can impersonate identities but read nothing itself. Borrow system:masters to read the production Secret. |
Recon
| Lab | What you do |
|---|---|
| First Contact | Pure local recon. Before you touch the network, find the secret the app leaked into the pod's own environment. |
| Who Am I | No kubectl, just a token and curl. Ask the API who you are and follow the one grant you were quietly given. |
| The Neighborhood | The API tells you nothing, but DNS never checks permissions. Map the cluster from what the pod already knows and reach an internal service. |
Privilege Escalation
| Lab | What you do |
|---|---|
| Pod Creation Escalation | You can create pods but read nothing. Launch a pod that runs as a powerful build account and have it hand you the flag. |
| RoleBinding Self-Grant | You can create RoleBindings. Find the one verb that defeats Kubernetes' escalation check, grant yourself Secret access, and read the flag. |
Lateral Movement
| Lab | What you do |
|---|---|
| Image Pull Secret Theft | A harmless-looking Secret-read grant exposes the cluster's imagePullSecret. Harvest it and recover the registry credentials. |
| Pod Exec Lateral Movement | You can exec into pods in ops. Drop into a CI pod and use its mounted token to read a production Secret. |
Node Token Harvest eBPF |
With node filesystem access, harvest another pod's kubelet-written token to pivot - while the sensor catches you reading it off the node. |
Egress Beacon Detection eBPF |
Beacon to a collector on the C2 port. Tetragon hooks tcp_connect and logs the connection at the socket the instant you make it. |
Node Escape
| Lab | What you do |
|---|---|
| hostPath Node Escape | A careless hostPath mount of the node root dissolves the container boundary. Read a root-owned file on the node itself. |
Privileged Pod Breakout eBPF |
A privileged, hostPID pod reaches the host via /proc/1/root. Break out, then watch the sensor catch the dereference. |
Persistence
| Lab | What you do |
|---|---|
| Sidecar Injection | Patch a Deployment in ops to inject a container that inherits a powerful workload's token. |
| Static Pod Persistence | Write to the kubelet's static-pod directory. It runs your manifest with no API server, admission, or RBAC in the way. |
| Malicious Admission Webhook | Register a mutating webhook that injects a container into every production pod the API server admits. |
Research kernel
| Lab | What you do |
|---|---|
| Kernel Driver Research - Dev | An on-demand kernel VM with KASAN + KCOV + BTF and a full toolchain, mitigations off. Build and insmod the sample vulnerable driver, trip it under KASAN, groom a slab reclaim to overwrite cred. |
| Kernel Driver Research - Hard | The same instrumented kernel with production mitigations (KASLR, hardened freelist, RANDOM_KMALLOC_CACHES, static usermodehelper). Cross-cache, KASLR leak, data-only cred overwrite. |
| Layer | What it uses |
|---|---|
| Backend | Go (stdlib net/http + ServeMux), client-go, pgx (raw SQL), golang-jwt, log/slog, Swagger via swaggo |
| Frontend | React 18, Vite 5, Bun, Tailwind + Radix, TanStack Query, @xterm/xterm; terminal over WebSocket, Defender over SSE |
| Data | PostgreSQL (users, progress, leaderboard, drivers) |
| Lab runtime | Nested k3s inside Kata Containers + Firecracker microVMs; a shared foothold image; airgapped image tarballs |
| Sensor | Tetragon (eBPF) for the Defender pane; KASAN + KCOV + BTF research guest kernels |
| Platform | Helm + ArgoCD (GitOps), Cilium (CNI + NetworkPolicy), cert-manager, HashiCorp Vault, Terraform (Hetzner), Grafana/Loki/Alloy |
Fast path - API + Postgres, no cluster. Good for auth, the catalog, and the course UI.
cp secrets/backend.env.local.example secrets/backend.env # dummy values are fine
docker compose up # backend + postgres (DEV_LOGIN=1)
cd services/frontend && bun install && bun run dev # http://localhost:7373Full path - Tilt + k3d, a real cluster with live session provisioning (sessions run under runc locally).
tilt up
cd services/frontend && bun install && bun run devFull prerequisites and the exact k3d / Cilium / cert-manager bring-up are in docs/self-hosting.md.
K8 Labs runs on a small, cheap footprint. The reference deployment is a two-node Hetzner setup
(a cloud VM for the control plane and app, a bare-metal box for the microVM lab node - nested virtualization needs real hardware),
with a budget single-box option that fits a ~$70/month budget. Full guide and Terraform: docs/self-hosting.md.
A live instance ran under a public bug bounty for a month: a ~$1,000 (ETH) pot to escape a lab's microVM to the underlying host, and no one broke in - read the announcement.
Every lab ships with intentional vulnerabilities - that is the point. They only ever run inside a disposable,
isolated nested cluster, and lab pods get no cluster credentials by construction. Do not deploy the lab manifests
into a cluster you care about. Found a problem in the platform itself? See SECURITY.md.
|
forefy |
PRs welcome - new labs (see AUTHORING.md and CONTRIBUTING.md),
fixes, and docs. A good lab teaches one specific misconfiguration or technique and ends in a captured flag.
MIT licensed · © forefy