Skip to main content
Exposed ServiceCritical

Exposed Kubernetes API Server

An exposed Kubernetes API server is a kube-apiserver endpoint (default TCP 6443, or the legacy insecure port 8080) reachable from the internet where anonymous access or over-broad RBAC lets an unauthenticated attacker enumerate and ultimately control the entire cluster.

The kube-apiserver is the single front door to a Kubernetes cluster: every kubectl command, controller, and node talks to it, and it brokers access to secrets, workloads, and the underlying compute. When that door is reachable from the public internet, the only things standing between an attacker and the cluster are authentication and RBAC and both have well-known failure modes. A server that still honors the deprecated insecure port, or one that binds the anonymous system:unauthenticated identity to powerful roles, turns a routine internet scan into a path to full cluster-admin. Because the API is self-describing, the same endpoints that operators rely on (/version, /api, /apis) are exactly what an attacker reads first.

Reviewed by Aakash Harish

Security Research Contributor, Legba

Reviewed 2026-05-28 · Updated 2026-05-28

What it is

An exposed Kubernetes API server is a kube-apiserver whose REST endpoint is reachable from untrusted networks in a state that permits unauthenticated or under-authorized access. There are two distinct root causes. The first is the legacy insecure port (historically 8080/TCP, enabled via --insecure-port on older releases): it serves plain HTTP with no TLS, no authentication, and no authorization, so anyone who can reach it acts as an implicit cluster-admin. This port was deprecated and removed in Kubernetes 1.20, but unpatched or long-lived clusters can still expose it. The second, and more common on modern clusters, is the secure port (6443/TCP, or 443/8443 behind a load balancer) combined with permissive configuration: when --anonymous-auth is left at its default and an authorization mode other than AlwaysAllow is in use, requests with no credentials are assigned the username system:anonymous in the group system:unauthenticated. If a cluster operator has bound that group (or system:authenticated, or a wildcard) to a powerful ClusterRole, the API answers privileged requests with no token at all. RBAC misconfiguration the unintended grant of list, get on secrets, create on pods, or escalate/bind verbs to a low-trust subject is the difference between a reachable API and a captured cluster.

A Kubernetes cluster concentrates an organization's most sensitive material in one control plane: Secret objects holding database passwords, cloud IAM credentials, TLS private keys, and registry tokens; the workloads that run the business; and, on many clusters, a direct path to the cloud account through node instance metadata. Lose the API server and you have not lost one host you have lost everything it orchestrates. The stakes are concrete. In 2018, researchers at RedLock found Tesla's Kubernetes administration console exposed with no password; intruders used it to read AWS credentials from the cluster and run cryptomining on Tesla's cloud, as reported by CNBC. That pattern unauthenticated control-plane access leading to credential theft and resource abuse is exactly what an open kube-apiserver invites, only worse, because the API server can also create privileged pods, read every Secret, and execute commands inside running containers. The NSA and CISA Kubernetes Hardening Guidance singles out strong authentication and authorization for the API server as a core mitigation precisely because its compromise is catastrophic. What your team actually needs is not another open-port alert but a confirmed answer to one question: can an unauthenticated request to this endpoint read Secrets or create workloads? If yes, you are one curl away from ransomware, data theft, and a pivot into your cloud.

At a glance

Typeexposed-kubernetes-api
Ports6443, 8080, 443, 8443
ProtocolsHTTPS, HTTP, TCP
Seen onKubernetes, kube-apiserver, Amazon EKS, Google GKE, Azure AKS, OpenShift, Rancher, k3s, kubeadm
SeverityCritical
Updated2026-05-28

How attackers find and exploit it

  • Discover candidate control planes by scanning the internet with Shodan, Censys, or masscan for hosts answering on 6443/TCP, 8443, or a legacy 8080, filtering on the kube-apiserver TLS certificate (which commonly carries subject alternative names like kubernetes, kubernetes.default, or the cluster's apiserver hostname).
  • Fingerprint the target by requesting GET /version, which returns the exact Kubernetes major/minor version and git commit, and GET /api and GET /apis, which enumerate the served API groups confirming the host is a kube-apiserver and revealing its version for vulnerability matching.
  • Test for the deprecated insecure path first: a plain HTTP request to http://<host>:8080/api with no TLS and no credentials that returns API data means full cluster-admin with zero authentication required.
  • Probe anonymous access on the secure port by sending unauthenticated requests such as GET https://<host>:6443/api/v1/namespaces and GET /apis/rbac.authorization.k8s.io/v1/clusterrolebindings; a 200 with data (rather than a 401/403) confirms system:anonymous has been granted real permissions.
  • Map the granted privileges by calling the SelfSubjectRulesReview / SelfSubjectAccessReview APIs (the same checks kubectl auth can-i runs) as the anonymous identity to learn exactly which verbs and resources are reachable without escalating noisily.
  • Harvest credentials by listing and reading Secret objects (GET /api/v1/secrets) to extract service-account tokens, cloud IAM keys, and registry passwords pivoting from cluster compromise into the surrounding cloud account.
  • Escalate to code execution and persistence by creating a privileged or hostPath-mounting Pod, or by using the pods/exec subresource to run commands inside an existing container then deploy cryptominers, ransomware, or a reverse shell, mirroring real-world campaigns against exposed clusters.

How to detect it on your surface

  • Inventory every internet-reachable host that answers TLS on 6443, 8443, or 443 with a kube-apiserver-style certificate, plus any host answering plain HTTP on 8080 use external scanning, not just your internal cluster list, because managed-cluster public endpoints and forgotten lab clusters are the usual culprits.
  • For each candidate, request /version and /api unauthenticated and record whether the endpoint is a kube-apiserver and what version it reports (anything serving an insecure 8080 is automatically a Critical finding).
  • Send unauthenticated read requests to representative resources (for example /api/v1/namespaces and /api/v1/secrets) and classify the response: a 401/403 indicates authentication/authorization is enforced; a 200 with cluster data indicates anonymous access is dangerously permissive.
  • Review the control-plane configuration directly: confirm --anonymous-auth=false (or that no ClusterRole is bound to system:anonymous / system:unauthenticated), and confirm no --insecure-port / --insecure-bind-address is set on the kube-apiserver.
  • Audit RBAC for over-broad grants: enumerate ClusterRoleBindings and RoleBindings whose subjects include system:unauthenticated, system:authenticated, or wildcard groups, and any binding to cluster-admin that an external identity could reach.
  • Check cloud security groups, firewall rules, and managed-cluster public-endpoint settings (EKS/GKE/AKS) for any rule permitting 0.0.0.0/0 to the API port; prefer a private endpoint or an allowlisted CIDR.

Detection signals

  • A JSON response to GET /version containing major, minor, gitVersion (for example v1.29.4), and platform fields the canonical kube-apiserver fingerprint.
  • GET /api returning an APIVersions object listing v1, and GET /apis returning an APIGroupList enumerating groups such as apps, batch, and rbac.authorization.k8s.io.
  • A plain HTTP (non-TLS) service on 8080 that returns API data with no WWW-Authenticate challenge and no credentials a hallmark of the deprecated, removed-in-1.20 insecure port.
  • On 6443, an unauthenticated request returning HTTP 200 with resource data instead of a 403 Forbidden whose message references system:anonymous (the expected, healthy response on a hardened cluster).
  • A TLS certificate whose subject or SAN list includes kubernetes, kubernetes.default, kubernetes.default.svc, or kube-apiserver, frequently signed by a cluster-internal CA named kubernetes.
  • Liveness/readiness endpoints such as /healthz, /livez, and /readyz responding, alongside /openapi/v2 serving the full API schema another strong control-plane indicator.

Validate before you report

  • Confirm the host is a real kube-apiserver (not a look-alike proxy) by parsing GET /version for the gitVersion/gitCommit fields and GET /apis for the standard Kubernetes API group list before asserting any exposure.
  • Prove anonymous reachability non-destructively: issue an unauthenticated GET /api/v1/namespaces and capture whether it returns a NamespaceList (true positive) or a Status object with reason Forbidden referencing system:anonymous (properly secured).
  • Determine the actual blast radius without modifying anything by submitting a SelfSubjectAccessReview/SelfSubjectRulesReview as the anonymous identity to enumerate exactly which verbs and resources (especially secrets, pods/exec, and create) are permitted this is the evidence that separates a low-impact read from a cluster-takeover.
  • Distinguish the insecure-port case by attempting plain HTTP on 8080: a successful unauthenticated API read over HTTP confirms the most severe variant (implicit cluster-admin), whereas a refused connection rules it out.
  • Capture read-only evidence only the /version banner, the redacted response status/headers, and the can-i style permission map and never create, delete, or exec against a production or third-party cluster during validation.

What looks like this but isn't

  • A health-check or metrics endpoint exposed by design: many clusters intentionally allow unauthenticated /healthz, /livez, /readyz, or /metrics. A 200 on those alone is not an exposure confirm that authenticated resources like namespaces or secrets are also readable anonymously before escalating.
  • An API gateway, reverse proxy, or honeypot that returns Kubernetes-looking responses: verify the /version git commit and API-group structure are internally consistent and, ideally, that the TLS chain matches a real cluster CA, so you do not flag a decoy or an unrelated service spoofing the banner.
  • A request returning 401 rather than 200: a 401 means anonymous auth is effectively disabled or a token is required; that is a secured control plane, not an open one only an unauthenticated 200 to a privileged resource is a confirmed positive.

Remediation

  • Eliminate the legacy insecure port immediately: ensure the kube-apiserver runs no --insecure-port / --insecure-bind-address (removed in Kubernetes 1.20) and upgrade any cluster old enough to still offer 8080 unauthenticated.
  • Disable anonymous access on the secure port by setting --anonymous-auth=false on the API server (keeping a narrowly scoped exception only for specific health endpoints if your tooling requires it), so unauthenticated requests are rejected outright.
  • Remove the dangerous RBAC bindings: delete or scope down any ClusterRoleBinding/RoleBinding whose subject is system:anonymous, system:unauthenticated, or system:authenticated, and ensure no low-trust subject is bound to cluster-admin or to roles granting secrets, pods/exec, or escalate/bind.
  • Restrict network reachability of the API server: place it behind a private endpoint or an allowlisted CIDR, and configure cloud security groups, firewalls, and managed-cluster settings (EKS/GKE/AKS authorized networks) so 6443/8443/443 are never open to 0.0.0.0/0.
  • Assume compromise if the endpoint was ever open: rotate every Secret, service-account token, cloud IAM credential, and certificate the cluster held; review audit logs for unexpected pod creation, exec sessions, or secret reads; and rebuild any node or workload you cannot prove is clean.
  • Adopt least-privilege RBAC going forward use specific Roles over ClusterRoles, avoid wildcards in verbs and resources, enable the API server audit log, and require strong authentication (OIDC, client certificates, or short-lived tokens) for all human and machine identities then retest the endpoint externally to confirm anonymous and unauthenticated requests are refused.

Operational checklist

  • Continuously monitor the external attack surface for any new host answering on 6443/8443/8080 with a kube-apiserver fingerprint, so a freshly stood-up or temporary cluster is caught within hours rather than after an attacker indexes it.
  • Enforce secure defaults in infrastructure-as-code and admission policy: provision API servers with --anonymous-auth=false, no insecure port, private or allowlisted endpoints, and block any manifest that binds system:unauthenticated or grants cluster-admin to broad subjects.
  • Run scheduled RBAC audits (for example with kubectl auth can-i --list across identities, or an automated analyzer) to catch privilege creep, wildcard grants, and orphaned bindings to powerful roles.
  • Keep clusters on a supported, patched Kubernetes version and track CISA Known Exploited Vulnerabilities and upstream security advisories for the control-plane components you run.
  • Enable and centralize API server audit logging with alerting on anonymous requests, secret reads, privileged pod creation, and exec into containers so control-plane abuse is detected in near real time.
  • Apply network segmentation and a deny-by-default posture so the control plane is reachable only from bastions, CI runners, and operator networks you explicitly name, with all administrative access brokered over a VPN or identity-aware proxy.

What to do next

An exposed Kubernetes API server is not one finding among many it is the finding that can hand an attacker your Secrets, your workloads, and a pivot into your cloud account, as Tesla learned when an unprotected console leaked its AWS credentials. The fastest way to cut the risk is to get a confirmed, evidenced answer to one question: does an unauthenticated request to this endpoint actually read Secrets or create pods? If it does, treat it as an active incident close the insecure port, set --anonymous-auth=false, strip the over-broad RBAC binding, and put the API behind an allowlisted private endpoint today, then rotate every credential the cluster ever held.

Methodology

Each finding-type guide is built from Legba Recon's real detection and validation logic, reviewed by a named security contributor, and cited against primary sources such as OWASP, CISA, NIST, and MITRE. We update pages when the underlying guidance changes. See our contributors and company.

FAQs.

References.

Weakness references (CWE)

Keep exploring

Your agent needs its Legba.

Read the docs