Kubernetes Security Deep Dive

Go beyond container basics: RBAC misconfiguration, admission control, NetworkPolicy, container-escape vectors, and why Kubernetes Secrets aren't encrypted by default.

expert 80m 3 tasks

Learning Objectives

  • Explain Kubernetes RBAC and how an over-permissioned ServiceAccount enables lateral movement
  • Explain admission controllers as the enforcement point for cluster-wide security policy
  • Apply NetworkPolicy to restrict pod-to-pod traffic beyond Kubernetes' default allow-all networking
  • Explain the risks of privileged containers and hostPath mounts as container-escape vectors
  • Describe why 'stored as a Secret' isn't the same as 'encrypted' in Kubernetes

Beyond "Container Security 101"

"Container Security: Docker & Kubernetes" introduced the basics. This lesson goes deeper into Kubernetes-specific attack surface: RBAC misconfiguration, admission control, network policy, and the container-escape vectors that turn a single compromised pod into full cluster compromise.

Kubernetes RBAC: Roles, Bindings, and Over-Permissioned ServiceAccounts

Kubernetes RBAC grants permissions via Role/ClusterRole objects bound to a subject (user, group, or ServiceAccount) through a RoleBinding/ClusterRoleBinding. Every pod runs as a ServiceAccount by default, and its associated token is automatically mounted into the pod's filesystem — meaning compromising one over-permissioned pod can hand an attacker that ServiceAccount's full RBAC permissions across the cluster, not just that one pod.

# Dangerously broad: effectively cluster-admin
kind: ClusterRoleBinding
subjects:
- kind: ServiceAccount
  name: my-app-sa
roleRef:
  kind: ClusterRole
  name: cluster-admin

Admission Controllers: The Cluster's Policy Enforcement Point

Admission controllers intercept requests to the Kubernetes API after authentication/authorization but before an object is persisted, and can reject or mutate it. This is where cluster-wide security policy actually gets enforced — e.g. rejecting any pod spec that requests privileged mode, or requiring images to come from an approved registry. Pod Security Standards (the modern replacement for the deprecated PodSecurityPolicy) are typically enforced this way.

NetworkPolicy: Kubernetes Defaults to Allow-All

Without any NetworkPolicy defined, every pod in a cluster can reach every other pod, by default — flat, unrestricted networking. A NetworkPolicy resource restricts this explicitly, similar in spirit to security groups/firewall rules but scoped to pod labels and namespaces rather than IP addresses:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
  podSelector:
    matchLabels: { app: payments }
  ingress:
  - from:
    - podSelector:
        matchLabels: { app: api-gateway }

This example allows only pods labeled api-gateway to reach the payments pod — everything else is denied.

Container Escape Vectors

Vector Risk
Privileged containers (privileged: true) Grants nearly all host capabilities — a compromised privileged container is close to a compromised host
hostPath volume mounts Mounting the host's filesystem into a container can let a compromise write to sensitive host paths directly
Docker socket mount (/var/run/docker.sock) Grants full control over the host's container runtime — equivalent to root on the host

etcd and Secrets: Not Encrypted by Default

Kubernetes stores all cluster state, including Secret objects, in etcd — and by default, Secrets are stored in etcd as base64-encoded plaintext, not encrypted. Base64 is an encoding, not encryption; anyone with etcd read access (or a backup of it) can trivially decode every Secret in the cluster. Encryption at rest for etcd must be explicitly enabled.

Common Pitfalls

  • Binding cluster-admin to a ServiceAccount "just to get something working," then never revisiting it
  • Assuming Kubernetes Secrets are encrypted simply because they're a distinct object type from ConfigMaps
  • Deploying without any NetworkPolicy and relying entirely on application-layer authentication for pod-to-pod security
  • Allowing privileged containers or Docker socket mounts anywhere outside of narrowly justified infrastructure tooling

Every pod's ServiceAccount token is automatically mounted into its filesystem by default, extending its blast radius far beyond one pod.

✦ Answer the questions to complete this task

Why does compromising one over-permissioned pod matter beyond that single pod?

Kubernetes networking is flat and unrestricted until you explicitly define otherwise.

✦ Answer the questions to complete this task

Without any NetworkPolicy defined, how can pods in a Kubernetes cluster communicate by default?

Secrets get a distinct object type in the Kubernetes API, but that alone says nothing about how they're actually stored.

✦ Answer the questions to complete this task

By default, how are Kubernetes Secret values stored in etcd?

💪 Exercises & Challenges

📝 MCQ expert +20 XP

Kubernetes Security Deep Dive MCQ

Test your understanding of Kubernetes Security Deep Dive.

Start →
⚙️ Practical expert +35 XP

Scope Down an Over-Permissioned ServiceAccount

A pod's ServiceAccount is currently bound to cluster-admin via a ClusterRoleBinding, but the application only needs to read ConfigMaps in its own namespace. Write the correct Role and RoleBinding (nam

Start →
🚩 Challenge expert +60 XP

Trace the Cluster-Wide Secret Exposure

A cluster compromise investigation finds: an attacker gained code execution in a single pod running an internet-facing web application. That pod's ServiceAccount was bound to cluster-admin via a Clust

Start →