Severity: criticalApplies to: Any reachable cluster
A Kubernetes cluster doesn’t have one exposed surface — it has several, each
independently a path to owning everything. That’s what makes cluster security
different from a single service: you’re not closing one port, you’re accounting for
five distinct front doors, any one of which is the whole cluster.
The API server (6443).Secured with auth and RBAC
it’s meant to be reachable — but an internet-facing API server is a continuous
CVE and brute-force target, and if anonymous auth
is on with a stray system:unauthenticated binding, it’s open. A misconfigured
API server is kubectl for attackers.
The kubelet (10250). Every node runs a kubelet, and its API can exec into
pods and read their logs and secrets. Historically it allowed anonymous access
(--anonymous-auth=true, --authorization-mode=AlwaysAllow), and clusters still
ship that way. An exposed, unauthenticated kubelet is code execution in every pod
on that node — no API server involved:
Terminal window
curl-skhttps://node:10250/pods# every pod on the node
# and exec endpoints from there
etcd (2379).The whole cluster in one store,
secrets included. No RBAC in front of it — reach it without client-cert auth and
you read and write cluster state directly.
The dashboard. The Kubernetes Dashboard, exposed and granted a powerful
service account, was behind real-world breaches (famously Tesla’s, where an open
dashboard led to cryptomining in their cluster). If you run it, it must be behind
auth and never public.
A compromised pod. The one that doesn’t require any exposed control-plane
surface. An RCE in a public-facing app, plus a
mounted service account token and
a flat network, lets an attacker query the API and
reach every internal service — lateral movement from a single container. This is
the most common real path, and it’s why the workload-side controls matter as much
as the control-plane ones.