Skip to main content
Common Kubernetes misconfigurations and how to avoid them
  • Cloud Security
  • How Tos

Common Kubernetes misconfigurations and how to avoid them

Craig Dowey

18 Nov 2025 6 Min Read

TL;DR 

  • Open endpoints give attackers an easy route into your cluster 
  • Running privileged containers or with writable file systems makes compromise much easier 
  • Extra Linux capabilities give unnecessary privileges 
  • Pulling public images without checks can import vulnerabilities 
  • Not enforcing pod security admission leaves gaps in policy across namespaces 

Introduction 

Kubernetes has changed the way we deploy and scale workloads. It’s powerful, flexible, and very good at hiding a lot of complexity. It is also very good at hiding security problems until someone starts poking at it. 

Attackers usually take the path of least resistance. If they find an exposed API, dashboard, or port, that is often enough for them to gain a foothold. Once they are in, attackers can exploit misconfigurations to escalate privileges, move laterally and exfiltrate data.  

We have seen real incidents where a Kubernetes console was left open on the internet with no authentication. Attackers did not need anything clever. They just found it, logged in, and got to work. 

In this post we will walk through common Kubernetes misconfigurations we see during testing, why they matter, and what you can do to avoid them. 

Issue one: Access 

If a dashboard or API is left open to the public, it’s effectively an unlocked front door. Attackers don’t need much encouragement, they’re scanning all the time, and once they’re in they can dig around in data or move from one system to another. 

Common Kubernetes Ports 

Port Service Notes 
443 Kubernetes API Server Main control plane interface 
10250 Kubelet API Requires TLS, often misconfigured 
10255 Kubelet (read-only) Deprecated, frequently unauthenticated 
10257 Controller Manager Metrics Should not be public 
10259 Scheduler Metrics Should not be public 
2379 etcd Client Port Stores entire cluster state 
2380 etcd Peer Port Used for etcd cluster communication 
30000–32767 NodePort Range May expose internal apps externally 

Example – exposed Kubelet API 

Suppose someone scans a node and finds port 10255 open. This port often has no authentication, so visiting http://<node-ip>:10255/pods can reveal every running pod and its configuration, including environment variables that may contain secrets. If port 10250 is misconfigured too, the intruder could run commands inside containers or forward ports to gain remote access. 

How to fix it 

  • Use private node pools and avoid public IPs 
  • Apply network segmentation to restrict Kubelet ports 
  • Route administrative access through a bastion host or identity-aware proxy with multi-factor authentication 

Issue two: Insecure workloads 

Running containers as root is convenient during testing but dangerous in production. However, once an attacker compromises the container, it increases the possibility of them reaching the host system. Writable filesystems make persistence easier still. 

Better practice 

  • Specify a non-root user with runAsUser 
  • Disable privileged mode unless absolutely required 
  • Use a read-only filesystem to prevent unwanted changes 

Example configuration 

apiVersion: v1 
kind: Pod 
metadata: 
  name: secure-pod 
spec: 
  containers: 
    - name: secure-container 
      image: my-secure-image 
      securityContext: 
        runAsUser: 10001 
        runAsNonRoot: true 
        privileged: false 
        readOnlyRootFilesystem: true 
        allowPrivilegeEscalation: false 
        automountServiceAccountToken: false 

This limits privilege escalation, blocks token mounts, and enforces least privilege. 

Issue three: Misconfigured capabilities 

Linux capabilities define what a container can do. Leaving defaults in place or adding unnecessary ones increases the impact of any breach. 

Example risk 

A pod runs in privileged mode, mounts a host path such as /host-system, and retains full Linux capabilities. The attacker can then read /etc/shadow, modify SSH keys, or install persistent tools. 

Safer configuration 

apiVersion: v1 
kind: Pod 
metadata: 
  name: capability-pod 
spec: 
  containers: 
    - name: capability-container 
      image: my-capability-image 
      securityContext: 
        capabilities: 
          drop: ["ALL"] 
          add: ["NET_BIND_SERVICE"] 

This configuration removes all default and inherited capabilities, and assigns only those necessary, in this case “NET_BIND_SERVICE”.  

Issue four: Vulnerabilities in supply chain 

Not every image from a public registry can be trusted. Some are outdated; others may include tools that make exploitation easier. The familiar nginx:latest tag, for example, might not be patched. 

Good habits 

  • Pin image digests rather than using :latest 
  • Scan images in the build pipeline with Trivy or Grype 
  • Host images in a private registry such as Harbor, ECR or GCR 
  • Use signed images and verify them through Sigstore or SLSABlock unverified sources using admission controls 

A short delay for scanning is far cheaper than a cleanup after compromise. 

Issue five: Pod Security Admission (PSA) 

PodSecurityPolicy has been replaced by PSA, which enforces pod security through namespace labels. The three levels are: 

  • Privileged – minimal restrictions 
  • Baseline – blocks risky settings while allowing common configurations 
  • Restricted – enforces best practice for production 

Example configuration 

kubectl label namespace secure-app \ 
  pod-security.kubernetes.io/enforce=restricted \ 
  pod-security.kubernetes.io/audit=baseline \ 
  pod-security.kubernetes.io/warn=baseline 

Start in audit or warn mode, then enforce once you are confident that workloads comply. 

Testing PSA 

apiVersion: v1 
kind: Pod 
metadata: 
  name: insecure-pod 
  namespace: secure-app 
spec: 
  containers: 
    - name: test 
      image: busybox 
      command: ["sleep", "3600"] 
      securityContext: 
        runAsUser: 0 

Kubernetes should reject this pod with: 

“podSecurity: forbidden: running as root is not allowed by the ‘restricted’ policy level.” 

This is a good sign that the policy is working and you are protected. 

Conclusion 

In most cases, Kubernetes isn’t the problem, it’s the way it’s been set up. Keep your networks private, apply least privilege, scan your images, and turn on Pod Security Admission to stay on top of the basics. Security in Kubernetes is about getting the basics right consistently across cluster namespaces. The details may feel routine, but they make all the difference.