Skip to content
All posts

Kubernetes Security Scanning: The Misconfigurations That Matter

5 min readKubernetes · Security · DevOps · Cloud Native

Most Kubernetes incidents don't start with a zero-day. They start with a YAML field someone forgot to set. A container that runs as root, a hostPath mount nobody questioned, a Role that quietly grants * on *. These defaults are convenient, and that's exactly why they survive code review.

Kubernetes security scanning is how you catch those mistakes before they reach a cluster. This post walks through the manifest misconfigurations that genuinely matter, why each one raises your blast radius, the difference between static and runtime scanning, and how to fold scanning into your repo without touching a live cluster.

Why manifests are where the risk lives

Your Kubernetes manifests are the source of truth for how workloads run: their privileges, their network reach, their access to the host and the API server. By the time a Pod is scheduled, the security posture is already decided — it was decided in Git.

That's good news for defenders. It means most posture problems are visible in plain text, ahead of deployment, with no cluster access required. You don't need to wait for something to be running and exploitable to know it's misconfigured.

The misconfigurations that matter

Not every finding deserves equal attention. Here are the ones that consistently expand blast radius and show up in real-world compromises.

Misconfiguration Why it matters What good looks like
Privileged containers (privileged: true) Near-equivalent to root on the node; disables most isolation Drop privileged; grant only specific capabilities
hostPath mounts Direct access to the node filesystem; a path to escape and persistence Use PVs, emptyDir, or projected volumes
runAsNonRoot unset / runAsRoot Container processes run as UID 0, amplifying any RCE runAsNonRoot: true and a non-zero runAsUser
allowPrivilegeEscalation: true Lets a process gain more privileges than its parent (e.g. setuid) Set to false explicitly
Missing resource limits One workload can starve a node; enables denial-of-service Set CPU/memory requests and limits
No NetworkPolicy Flat networking — any compromised Pod can reach any other Default-deny, then allow-list required flows
Over-broad RBAC (* verbs/resources, cluster-admin) A leaked token becomes full cluster control Least-privilege Roles scoped to namespaces
Missing securityContext No read-only root FS, no dropped capabilities, weak defaults Define a hardened securityContext per container

Privilege and the host boundary

The most dangerous misconfigurations all weaken the boundary between a container and its node. privileged: true, hostPath, hostNetwork, and hostPID each hand a workload a piece of the host. Individually they're risky; combined, they turn a single compromised Pod into a node takeover — and from a node, lateral movement across the cluster is often trivial.

The fix is rarely complicated. Most workloads need none of these. The problem is that nothing stops you from setting them, so they slip in.

Identity is the new perimeter: RBAC

Over-broad RBAC is the quiet killer. A Role or ClusterRole with * verbs on * resources means any ServiceAccount token bound to it is a skeleton key. Attackers love these because they don't require an exploit — just a leaked or mounted token. Scope Roles to specific namespaces, verbs, and resource types, and avoid binding workloads to cluster-admin.

A hardened baseline in YAML

Most of the container-level fixes collapse into one block:

securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]

Pair that with explicit resource limits and a default-deny NetworkPolicy in the namespace, and you've eliminated the majority of high-severity manifest findings before anything is deployed.

Static manifest scanning vs. runtime

There are two broad ways to look for Kubernetes risk, and they answer different questions.

Static manifest scanning reads your YAML — Deployments, DaemonSets, Roles, NetworkPolicies — and evaluates it against hardening rules. It runs in your repo or pipeline, needs no cluster, and tells you what will be true once you deploy. It's fast, deterministic, and ideal as a gate on pull requests.

Runtime scanning observes a live cluster: actual Pods, admission decisions, drift, and behavior. It catches things manifests can't, like images that changed since deploy or resources created out-of-band. But it's reactive — by the time it flags something, the risk is already running.

You want both eventually, but static scanning gives you the highest leverage for the lowest cost: it shifts security left, catches issues while they're cheap to fix, and never requires production credentials.

How NANOTESTING scans your manifests

NANOTESTING runs Kubernetes security scanning in exactly this static, repo-first model. When you connect a repository for a deep scan, it discovers your Kubernetes manifest YAML and runs Kubescape in static-file mode against it — no kubeconfig, no cluster access, no agents to install.

Findings are scored against recognized hardening frameworks, including NSA-CISA Kubernetes hardening guidance and MITRE ATT&CK for Kubernetes, so each misconfiguration comes with context on the technique it enables, not just a rule ID. Results roll up into the same posture view as the rest of your scan — and map to compliance frameworks like CIS Controls v8, NIST CSF 2.0, SOC 2, and PCI DSS 4.0, with an overall A–F grade.

One principle worth calling out: honesty about coverage. If a check can't run — say a manifest isn't present or a tool can't evaluate it — NANOTESTING records that as a skip or coverage gap, never as a clean pass. A green result means the check actually ran and passed, which is the only kind of green worth trusting.

Kubernetes is one surface among several. The same connected scan also covers cloud posture, repository SAST, dependencies and secrets, web and API, mobile, and smart contracts — so your Kubernetes findings sit alongside the rest of your security picture rather than in a silo.

Takeaways

Kubernetes security scanning is most effective when it meets your manifests where they live: in Git, before deploy.

Fix it in the YAML, and you've fixed it everywhere that manifest deploys.

Related posts