The Kubernetes ecosystem has a habit of shipping admin endpoints without authentication. Not just one or two tools — dozens. And the pattern is consistent enough to call a design convention.

kcp just published CVE-2026-39429 (CVSS 8.2): the cache server on the root shard is directly accessible with no auth or authorization. Prior to 0.30.3 and 0.29.3, anyone who can reach the root shard can read and write the cache. That’s the latest entry in a catalog of Kubernetes-adjacent tools that assume their API surface is internal and gate it with nothing but network position.

This is not a kcp problem. It is a Kubernetes ecosystem problem.

What “internal” means to infrastructure tools

When you build a Kubernetes controller, operator, or control plane, you have two authentication options:

  1. TLS client certs. The Kubernetes-native approach. The server presents a cert, the client validates the CA, the connection is authenticated. Works everywhere inside the cluster. Simple. Boring.

  2. Bearer tokens (typically in Authorization: Bearer <token> headers). The REST API approach. Token is presented per-request. Works with most HTTP clients. Also simple. Also boring.

The third option — the one infrastructure tools reach for by default when they assume internal-only access — is no auth at all. The endpoint responds to any request. If you hit /health, you get health. If you hit /cache, you get the cache. If you hit /exec with the right payload, you get a shell.

Why does this convention exist? Three reasons:

  • Speed of iteration. Adding a cert pipeline or token middleware adds complexity to the boot sequence. An unauthenticated endpoint needs no certificates, no config, no secret mounts. It just works. On the first day.

  • The cluster boundary is the auth. If your tool lives inside a VPC, behind a private subnet, and reachable only from within the cluster’s pod network, you don’t need per-request authentication. The network layer is good enough.

  • Admin ports are assumed exclusive. Tools that listen on a dedicated admin port (e.g., :8443, :9090) assume that only operators connect there, so auth is overkill. A developer with kubectl port-forward or a curl from inside the pod doesn’t need credentials — they’re already inside.

The convention works until it doesn’t, and it doesn’t when someone misconfigures the admin port to listen on 0.0.0.0 instead of 127.0.0.1, or when a load balancer exposes it externally, or when a tool like kcp exposes its cache on a route that any pod in the cluster can reach.

The catalog of unauthenticated admin endpoints

Here are the tools in the Kubernetes ecosystem I have seen or read about with this pattern:

etcd — The canonical example. By default, etcd listens on port 2379 with no auth. The --client-cert-auth flag enables TLS client cert auth, but the default is open. If your etcd is exposed to the cluster network, anyone can read the entire key-value store containing secrets, configs, and pod specs. The fix has been in the docs since day one.

Kubernetes API server (/api, /apis, /version)/version and /api are unauthenticated. They return the API version list and cluster version. Not exploitable on their own, but they are the reconnaissance step before auth-based enumeration. /apis returns every API group the server exposes — a map of what the cluster can do.

Container registry sidecars — Tools like Harbor, JFrog, or simple registry deployments often have admin endpoints (/v2/_catalog, /api/v1/) that are unauthenticated or use only HTTP basic auth with weak defaults.

Prometheus and Grafana — Prometheus’s /api/v1/ query API is unauthenticated by default. Grafana’s admin API is often accessible with the default admin:admin credentials. Both are standard in any Kubernetes cluster, and both are often exposed externally for dashboards.

ArgoCD — The admin endpoint (/api/v1/session) is unauthenticated by default. Logging in with admin:password (or whatever the secret contains) gives full cluster management access. The argocd-server service is frequently exposed via ingress.

Portainer — The web API at :9000/api is unauthenticated by default, and the web UI defaults to admin:portainer. Common in smaller operations.

kcp (CVE-2026-39429) — The cache server on the root shard. Unauthenticated, read and write. Fixed in 0.30.3 / 0.29.3. CVSS 8.2.

The pattern: these are all tools that manage, observe, or extend a Kubernetes cluster. They are infrastructure tools. And they are all unauthenticated by default on their admin surfaces.

Why it matters for attackers

An unauthenticated admin endpoint gives you three things for the price of a single HTTP request:

  1. Recon. What does this cluster run? What API groups are registered? What namespaces exist? What config maps are mounted? The API server’s /api and /apis give you the first two; etcd gives you the rest.

  2. Read access. Secrets, config maps, deployment specs, service accounts, ingress rules, network policies, and pod specs are all readable from etcd or the API server with no auth. This tells you where the secrets live, what roles exist, and which workloads have privileged access.

  3. Write access. Depending on the endpoint: modify config maps (triggers deployments), write secrets, create new pods (with or without host network access), mutate deployments (patch the image field), and write to caches (which may propagate to serving layers).

The attack is trivial. The exploitation requires knowing which endpoint to hit and what it controls. The convention that “internal means safe” means most operators never check what their admin endpoints look like from outside the cluster.

How to audit your surface

You do not need a scanner for this. A single host and three endpoints tell you the story.

# 1. Check the API server
curl -sk https://<api-server>/version | python3 -m json.tool
curl -sk https://<api-server>/api | python3 -m json.tool

# 2. Check etcd if exposed
curl -sk https://<etcd>:2379/ | head -5
curl -sk -w "%{http_code}" https://<etcd>:2379/version

# 3. Check the admin port of any control plane tool
curl -sk https://<host>:<admin-port>/
curl -sk https://<host>:<admin-port>/health

If all three respond with JSON or HTML to unauthenticated requests, you have your surface. The question is not whether any individual endpoint is exploitable — it is how much read access they give you and whether any of them accept writes.

The fix

There are three levels, and each adds a layer of defense:

  1. Listen on 127.0.0.1. This is the single most effective fix and the one most tools default to. The admin port is only reachable from the host itself. If you need external access, use kubectl port-forward or an ingress with auth.

  2. Enable TLS client cert auth. Configure the etcd CA, mount it in pods, set the cert and key. Every internal client presents a cert. The server validates it against the CA. No tokens, no passwords, no defaults to forget.

  3. Enable RBAC and bearer tokens. The Kubernetes API server’s RBAC is the gold standard. Create roles for each service account. Grant only what is needed. Token-based auth per-request. The cost is configuration; the return is that every request is authenticated and authorized.

Level 1 catches 80% of the external exposure. Level 2 catches the rest of internal exposure (a pod on a shared network). Level 3 catches lateral movement within the cluster (a compromised pod querying the API server).

What this means for bug bounty and pentest

When you are working on a Kubernetes program scope, the admin endpoints are the low-hanging fruit. They are unauthenticated, well-known, and often left exposed. The technique:

  1. Discover the API server (certificate transparency, DNS, port scanning).
  2. Hit /version and /api — get the API version and registered groups.
  3. If etcd is exposed, pull secrets from /registry/secrets/<namespace>/<secret-name>.
  4. Check the cluster for exposed ingress controllers with admin endpoints (ArgoCD, Portainer, Grafana).
  5. For each, try the default credentials or unauthenticated API access.

This is not discovery-driven. It is procedural. You hit the known endpoints with known patterns. If the admin ports are closed or auth-protected, you move on. If they are open, you read the cache.

Trade-offs

Listening on 127.0.0.1 only works when the admin port is not needed externally. Some tools — especially those designed to be accessed by external CI/CD pipelines or operator dashboards — need public admin ports. In those cases, level 2 (TLS client certs) or level 3 (RBAC + tokens) becomes mandatory, not optional.

The trade-off is configuration complexity versus security surface. Tools that ship unauthenticated are easier to get running. Tools that require certs and tokens require a slightly more careful first-day setup. The difference is negligible for a human operator and massive for an attacker who is scanning.

The takeaway

The Kubernetes ecosystem’s convention of unauthenticated admin endpoints is not a bug. It is a design choice optimized for developer velocity inside the cluster. It works perfectly when the cluster is the perimeter and every tool is configured correctly. It fails when someone exposes an admin port to the outside, and it fails even more when the operator assumes that an internal port-forward is enough.

Your admin surface is not defined by what the tool does. It is defined by what the endpoint accepts without a token or cert. Audit it. Listen on 127.0.0.1 unless you need otherwise. Enable client cert auth if you expose the port. Enable RBAC if you expose the API. The convention is convenient, not correct.

Further reading