Shared Surface · Network
Networking
By default a Kubernetes cluster is one flat network. Every pod can reach every other pod, and the control plane itself becomes a bridge between tenants.
One flat LAN, by default
Out of the box, Kubernetes networking is completely open: every pod can talk to every other pod, across every namespace. Namespaces are an organisational boundary, not a network one. Unless you add NetworkPolicies (and run a CNI that enforces them), Tenant A’s workload can connect straight to Tenant B’s.
Network policies are the main tool for fixing this, and a default-deny policy in each tenant namespace is a good starting point (ideally before any workloads are deployed, as retrofitting them is a lot harder). They do have some limitations to be aware of though:
- Pods using
hostNetwork: truesit outside the CNI’s policy enforcement. - Policies that allow traffic based on a custom namespace label can be bypassed by a tenant who can label their own namespace (see the RBAC page).
- Nothing blocks access to the cloud metadata service (
169.254.169.254) by default, so that needs an explicit egress rule.
DNS
Another point to consider for multi-tenant clusters is that DNS is used for service discovery, and by default all workloads in a cluster use the same DNS database to store that information.
As a result, any tenant who can make DNS requests in the cluster will be able to enumerate all the services running in the cluster, and network policies don’t help, as the tenant only needs to talk to the cluster DNS server. CoreDNS-enum is a good example of a brute-force tool which can enumerate every service running in a cluster.
On its own, knowing a service exists doesn’t break the tenant boundary, but it’s a nice bit of reconnaissance for an attacker and could be a privacy issue where tenants are separate customers.
There’s not a great answer to this one. Virtual clusters give each tenant their own DNS, and the Kubernetes multi-tenancy docs mention a CoreDNS policy plugin that can restrict lookups by namespace. I’ve not seen anyone customise their cluster DNS like that in practice though, and I’m not sure how well it would stand up to a brute-force tool or whether it’s even possible on managed Kubernetes.
SSRF by design
Another concern with networking in multi-tenant clusters is that the Kubernetes API server provides a fully-fledged proxy, which is used for managing and troubleshooting applications deployed to the cluster.
As such, the API server will generally be able to reach any workload at the network level, so if a malicious tenant can misuse that feature to connect to other tenants’ workloads, they may be able to bypass network policies.
A good example of this comes from a 2019 blog by Kinvolk. They noted that a user who can edit a pod’s status can change the IP address listed there, and the API server will then use that modified address when proxying requests to the pod. A fix was added to stop the proxy connecting to loopback and link-local addresses (which blocks the cloud metadata service), but any other routable address, including pods in other tenants’ namespaces, is still reachable. This effectively allows for network policy bypass in a multi-tenant cluster.
Additionally, where nodes are shared, there are other SSRF vectors in Kubernetes which go via the Kubelet and could be used by attackers in this type of cluster.
Unpatchable CVEs
There are a couple of Kubernetes CVEs in the networking space that have never been patched, as fixing them would break legitimate functionality. Both are much more of a concern in a multi-tenant cluster than in a single-tenant one.
- CVE-2020-8554. A tenant who can create Services can set an
externalIPsvalue pointing at any address, and kube-proxy will then redirect traffic from other pods heading for that address to the tenant’s pod. That’s a man-in-the-middle on any other tenant talking to that IP. The fix here is to block ExternalIP services with theDenyServiceExternalIPsadmission controller or a policy engine. - CVE-2021-25740. Endpoints and EndpointSlices are namespaced, but nothing checks that the IP addresses in them belong to that namespace. A tenant who can write them can point a Service at another tenant’s pod. Traffic then arrives via a shared ingress controller or kube-proxy, which the victim’s network policy is likely set up to trust. Restricting tenant write access to Endpoints and EndpointSlices, or using per-tenant ingress controllers, helps here. N.B. Kubernetes removed this access from the default
editandadminroles in 1.22, but only for clusters created on 1.22 or later. If your cluster has been upgraded from an older version, tenants with those roles probably still have it.
Shared network components
Ingress controllers and service meshes are another shared component that can undo good network policies. ERNW’s Breaking Multi-Tenancy research had a couple of good examples of this:
- Istio. A
VirtualServicethat uses the specialmeshgateway applies its routing rules to every sidecar in the mesh, regardless of the namespace it was created in. So a tenant who can create Istio resources in their own namespace can redirect, intercept or drop other tenants’ traffic (ISTIO-SECURITY-2026-002). The same problem in Kubeflow, where tenants were given Istio edit rights, allowed theft of every user’s session cookie (CVE-2026-47237). - Traefik. Traefik blocks cross-namespace references in its CRDs by default, but the same references made via annotations on
Ingressobjects weren’t covered, letting a tenant attach another namespace’s middleware to their own routes.
The common thread is that anything where a tenant can influence a cluster-wide component is a problem. Annotations are particularly sneaky, as they’re not part of any schema and are often poorly documented.
References & further reading
- Kubernetes docs — Network Policies
- Kubernetes docs — Cluster Networking
- Abusing Kubernetes API server proxying
- Using the API server proxy to bypass network policies
- Kubernetes is a router
- CoreDNS enum
- CoreDNS policy plugin — Kubernetes metadata multi-tenancy policy
- Kubernetes SSRF
- Unpatchable Kubernetes vulnerabilities: CVE-2020-8554
- Kubernetes docs — DenyServiceExternalIPs admission controller
- CVE-2021-25740 proof of concept
- BREAKING MULTI-TENANCY IN KUBERNETES OVER AND OVER, AND WHAT WE CAN LEARN FROM THIS