Safeguard
Container Security

Kubernetes Security Best Practices for 2026

A default Kubernetes cluster trusts too much: root pods, flat networking, and readable secrets. Here are the hardening practices that actually move the needle in 2026.

Marcus Chen
Cloud Security Engineer
5 min read

A freshly installed Kubernetes cluster is optimized for developer velocity, not for containing a breach. Out of the box, pods run as root, any pod can reach any other pod on the network, secrets are stored base64-encoded rather than encrypted, and the default service account is mounted into every workload whether it needs API access or not. None of that is a bug — it is the price of a platform that has to run anyone's workload on day one. The problem is that most teams never revisit those defaults, so the cluster that shipped a hello-world demo is the same cluster now running customer data. Real incidents follow the same defaults: CVE-2018-1002105 let an unauthenticated user escalate to full cluster-admin through the API server's proxy handling, and the recurring pattern in cloud-native breaches is a single compromised container that had far more reach than it ever needed. Hardening Kubernetes is less about exotic controls and more about systematically walking back the trust the defaults hand out.

The 4C model: where do your controls actually live?

Kubernetes security is layered, and the community frames it as the "4Cs": Cloud, Cluster, Container, and Code. A control at one layer cannot fix a gap at another — an airtight pod security policy means nothing if the underlying node has a publicly exposed kubelet, and a perfectly locked-down cluster cannot save an application with a deserialization bug in its own code. The practices below map to the Cluster and Container layers, because those are the ones platform teams own directly and the ones attackers reach for first after a foothold.

1. Enforce Pod Security Admission on every namespace

PodSecurityPolicy was removed in Kubernetes v1.25, and Pod Security Admission (PSA) is its built-in replacement. PSA applies one of three profiles — privileged, baseline, or restricted — at the namespace level via labels. Set restricted everywhere you can; it forbids privilege escalation, requires non-root execution, and mandates a seccomp profile.

apiVersion: v1
kind: Namespace
metadata:
  name: payments
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/warn: restricted

Your workloads then need a security context that satisfies the profile:

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]
  seccompProfile:
    type: RuntimeDefault

Setting enforce-version: latest matters: it opts the namespace into new restrictions as the profile tightens across releases instead of pinning you to an old, looser definition.

2. Make the network deny-by-default

By default, every pod in a cluster can open a connection to every other pod. That flat topology is why a single compromised web frontend can so often reach a database it should never touch. NetworkPolicies flip the model to deny-by-default the moment one selects a pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: payments
spec:
  podSelector: {}
  policyTypes: ["Ingress"]

With that baseline in place, you explicitly allow only the traffic each service needs — frontend to API, API to database — and everything else is dropped. Lateral movement, the step that turns one compromised pod into a cluster-wide incident, becomes dramatically harder.

3. Encrypt secrets at rest and stop over-mounting them

Kubernetes Secrets are base64-encoded, not encrypted — anyone with etcd read access or a broad RBAC grant can decode them trivially. Enable encryption at rest with an EncryptionConfiguration backed by a KMS provider so the bytes in etcd are actually protected. Just as important, stop mounting the default service account token into pods that never call the Kubernetes API:

apiVersion: v1
kind: Pod
metadata:
  name: batch-job
spec:
  automountServiceAccountToken: false

An unused token sitting in a filesystem is a credential waiting to be exfiltrated.

4. Lock down the control plane and nodes

Disable anonymous authentication on the API server, turn on audit logging, and set the kubelet to --anonymous-auth=false with webhook authorization so a compromised node cannot query or mutate other pods. Keep the cluster patched: container-escape and privilege-escalation CVEs in the runtime and kernel — from the runc breakout family to Linux kernel bugs like Dirty Pipe (CVE-2022-0847) — are exploitable precisely because they bridge the container-to-host boundary that everything else assumes is solid.

Hardening checklist

ControlDefault stateHardened state
Pod securityUnrestrictedrestricted PSA enforced per namespace
Container userrootNon-root, no privilege escalation
Root filesystemWritablereadOnlyRootFilesystem: true
NetworkFlat, all-to-allDeny-by-default NetworkPolicy
Secretsbase64 in etcdEncrypted at rest via KMS
Service account tokenAuto-mountedMounted only where needed
API serverAnonymous auth onAnonymous off, audit logging on
ImagesAny registry, any tagSigned, pinned, policy-gated on admission

How Safeguard helps

Enforcing these controls by hand across dozens of namespaces and hundreds of manifests is where drift creeps in — a namespace ships without the restricted label, a NetworkPolicy never lands, a workload quietly runs as root. Safeguard's infrastructure-as-code scanning reads your Kubernetes manifests and Helm charts in the pull request and flags the misconfigurations above before they reach a cluster, so the security context and PSA labels are checked the same way you check unit tests. For what runs on the nodes, Safeguard's container security scans the images your pods pull and gates admission on signature and vulnerability policy, and Griffin AI prioritizes findings by whether the vulnerable code path is actually reachable, so your team fixes the handful of exploitable issues instead of drowning in raw CVE counts. If you are weighing platforms, our comparison hub breaks down how this approach differs from posture-only tools.

Kubernetes will not harden itself, but you do not have to do it manually either. Create a free Safeguard account to scan your manifests and images today, or read the Safeguard documentation for step-by-step setup.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.