Back

K10: Outdated and Vulnerable Kubernetes Components - Overview

What are Outdated and Vulnerable Components?

K10: Outdated and Vulnerable Kubernetes Components is the final entry in the OWASP Kubernetes Top 10. It covers a simple but stubborn failure: running Kubernetes itself, its add-ons, or the underlying node operating system and container runtime at versions that carry known, publicly documented vulnerabilities—or that have passed end-of-support and no longer receive security fixes at all. The weakness is not a subtle logic flaw you have to discover; it is a published advisory with a patch already available, applied everywhere except your cluster.

A Kubernetes cluster is not one program—it is a stack of independently versioned components that each ship on their own release cadence. The control plane (API server, scheduler, controller-manager, etcd), the per-node kubelet and kube-proxy, the container runtime (containerd, CRI-O, or legacy Docker/dockershim), the CNI network plugin, CSI storage drivers, the ingress controller, the metrics and dashboard add-ons, service-mesh sidecars, and the node OS kernel are all moving parts. Every one of them accrues CVEs over time. K10 is the accumulated gap between the versions that have been patched upstream and the versions actually running in your cluster.

Core Concept

A maintained cluster:
  Kubernetes version   -> within the supported release window (N, N-1, N-2)
  Version skew         -> kubelet no more than 3 minors behind API server
  Container runtime    -> containerd/CRI-O patched, dockershim removed
  Node OS / kernel     -> supported release, security updates applied
  Add-ons              -> ingress, CNI, CSI, dashboard, mesh all current
  CVE tracking         -> subscribed to k8s security-announce feed
  Inventory            -> every component + version known and owned
  Upgrade cadence      -> regular, tested, automated where possible

An outdated cluster (K10):
  Kubernetes version   -> end-of-life, no more patches, months/years behind
  Version skew         -> kubelet/API server outside the supported skew
  Container runtime    -> unpatched runc/containerd with escape advisories
  Node OS / kernel     -> EOL distro, kernel with public LPE exploits
  Add-ons              -> ingress controller / dashboard with known RCE
  CVE tracking         -> nobody watches advisories for the k8s stack
  Inventory            -> "we're not sure what version that is"
  Upgrade cadence      -> "if it isn't broken, don't touch it"

Why It's Its Own Category

Kubernetes deserves a dedicated "outdated components" entry—separate from generic application-dependency risk—for reasons specific to how clusters are built and operated:

Why Does This Matter?

Business Impact

Technical Impact

Technical Context

The Components That Age

LayerExamplesWhat an outdated version risks
Control planekube-apiserver, scheduler, controller-manager, etcdAPI-server privilege escalation, DoS, auth bypass classes
Node agentskubelet, kube-proxyPrivilege-escalation and path-handling CVEs on every node
Container runtimecontainerd, CRI-O, runc, legacy Docker/dockershimContainer escape to the host (runc-escape class)
Node OS / kernelUbuntu, RHEL, Bottlerocket, Flatcar, Amazon LinuxLocal privilege escalation via kernel exploits; EOL = no patches
Networking (CNI)Calico, Cilium, Flannel, WeaveNetwork-policy bypass, node-level code execution
Storage (CSI)EBS/GCE/Ceph drivers, provisionersHost path handling, privileged mount abuse
Ingress / gatewayingress-nginx, Traefik, HAProxy, Envoy/gatewayUnauthenticated RCE and config-injection (IngressNightmare class)
Add-onsKubernetes Dashboard, metrics-server, cert-managerDashboard auth bypass, information disclosure
Service meshIstio, Linkerd (control plane + sidecars)Proxy CVEs replicated across every meshed pod

The Support and Skew Rules That Force Action

Kubernetes is not a "set and forget" platform. Two upstream rules turn "we're a bit behind" into a hard operational problem:

Supported releases:
  Upstream maintains roughly the three most recent minor
  versions (N, N-1, N-2). Older minors stop receiving
  patch releases entirely -> known CVEs are simply never fixed
  for you.

Version skew (must stay inside these bounds):
  kubelet        -> up to 3 minor versions older than kube-apiserver
  kube-proxy     -> matched to the node's kubelet
  controller/    -> at most 1 minor older than kube-apiserver
    scheduler
  kubectl        -> within 1 minor of the API server

Consequence: you cannot skip several minors in one jump.
Fall far enough behind and the only path forward is a
sequence of sequential, tested upgrades -- or a rebuild.

Why Clusters Fall Behind

Real-World Impact

The cases below are described as vulnerability classes tied to well-known, publicly discussed events. Specific CVE identifiers and exact figures are deliberately omitted—the durable lesson is the pattern, not a number to memorise.

Class 1: Ingress-Controller Remote Code Execution (the "IngressNightmare" class)

The pattern: The ingress controller is a cluster component that parses attacker-influenced configuration (annotations, snippets) and terminates external traffic. A class of publicly disclosed flaws in widely used ingress controllers allowed a request or a crafted Ingress object to inject configuration or trigger code execution in the controller's pod.

Why it matters: The ingress controller is internet-facing and typically runs with broad permissions—it can read Secrets (TLS certificates) and watch cluster resources. Code execution there is not a leaf-node compromise; it is a foothold with cluster-wide reach. Clusters running an outdated ingress version long after a fix shipped remained exploitable purely because they were never upgraded.

Root cause for K10: A known, patched vulnerability in a core add-on left running at the vulnerable version.

Class 2: Container Runtime Escape (the "runc-escape" class)

The pattern: runc is the low-level runtime that containerd and CRI-O use to actually start containers. Publicly disclosed flaws in this class allowed a malicious or compromised container to overwrite the host runc binary or otherwise break out of its isolation and execute code on the node.

Why it matters: A runtime escape converts "attacker controls one pod" into "attacker controls the node"—and from a node, every pod, Secret, and ServiceAccount token scheduled there. Because a single runc version underlies most clusters, the blast radius of an unpatched runtime is enormous. The fix is a runtime/runc upgrade on every node; clusters that never rolled it out stayed escapable.

Root cause for K10: An unpatched container runtime on the nodes.

Class 3: Kubelet / API-Server Privilege Escalation

The pattern: Over the project's history, several disclosed flaws in the kubelet and the API server allowed a client to escalate privileges, reach endpoints without proper authorization, or proxy to backends it should not. These were fixed in specific patch releases.

Why it matters: The kubelet and API server are the control surfaces of the cluster. A privilege-escalation flaw here can turn a limited service account or a compromised node into cluster-admin-equivalent access. The defense is simply to be on a patched version—which clusters outside the supported window are not.

Root cause for K10: Control-plane / node-agent components running below the patched version, or entirely end-of-life.

Prevalence and Statistics

Outdated components are among the most reliably present findings in real clusters, precisely because staying current is ongoing work that competes with feature delivery. Rather than quote a single figure—numbers vary widely by survey and year—the defensible picture is:

Treat any single percentage as illustrative. The durable takeaway: known-vulnerable and end-of-life components are common, trivially fingerprinted, and exploited with off-the-shelf tooling.

Common Misunderstandings

Myth 1: "If the cluster is running fine, the version is fine"

Reality: A vulnerable component runs exactly as smoothly as a patched one—until it is exploited. Stability is not security. An end-of-life version can be perfectly stable and completely unpatched at the same time.

Myth 2: "We scan our application images, so we're covered"

Reality: Image scanning finds vulnerable libraries inside your containers. It says nothing about the kubelet, the runtime, the CNI, or the ingress controller—the components that actually sit at the escape and RCE boundary. K10 requires scanning the cluster stack itself, not just workloads.

Myth 3: "Upgrading is too risky to do often"

Reality: The risk of a tested, incremental upgrade is far smaller than the risk of an emergency multi-version jump forced by an active exploit or an expiring support window. Frequent small upgrades are how you keep upgrades boring.

Myth 4: "Managed Kubernetes patches everything for us"

Reality: Managed control planes automate a lot, but you usually still own when node pools upgrade, which node OS/AMI they run, and every add-on you installed yourself. A managed cluster with a year-old node pool and an unpatched ingress chart is still a K10 cluster.

Myth 5: "We're on a recent Kubernetes version, so components are current"

Reality: The Kubernetes version and the versions of runc, the kernel, the CNI, and third-party add-ons move independently. A current API server can sit on top of an unpatched runtime or an EOL kernel. Each layer needs its own tracking.

Myth 6: "There's no exploit for our exact version, so we're safe"

Reality: Advisories are published with patches, and public exploits follow quickly for popular components. "No exploit yet" is a countdown, not a guarantee—and for end-of-life versions there will never be a fix at all.

How to Identify if You're Vulnerable

Ask these questions about your cluster:

If you answered "no" or "not sure" to several of these, you very likely have known-vulnerable or end-of-life components in your cluster today.

Key Takeaways

  1. A cluster is a stack of independently versioned parts—control plane, kubelet, runtime, kernel, CNI/CSI, ingress, and add-ons each age on their own.
  2. Known-vulnerable means exploited-by-catalogue—once your version is fingerprinted, the exploit already exists.
  3. Version skew and end-of-life are hard deadlines—fall too far behind and you lose both patches and the ability to upgrade smoothly.
  4. The dangerous layers are the ones below your app—runtime and kernel escapes, ingress RCE, and API-server privesc live in the cluster, not your image.
  5. Currency is a process, not a state—inventory, CVE tracking, scanning, tested upgrades, and automated node patching keep K10 closed.

Next Steps