Cluster posture scanning, and the six findings that are always there

Every Kubernetes benchmark scan produces hundreds of findings and the same handful matter. Here is which ones, why the control plane checks mostly do not apply on managed clusters, and how to stop the report being ignored.

Run a posture scan against a cluster that has never had one and you get several hundred findings. Nobody reads several hundred findings. The report is circulated, acknowledged, and filed, and the cluster stays exactly as it was.

The scan is still worth running. The work is in knowing which findings matter, which are noise in your context, and how to present the result so that something changes.

What the tools do, and where they differ

kube-bench checks a cluster against the CIS Kubernetes Benchmark. It is focused, mature and the standard reference, and a large share of its checks concern control plane configuration: API server flags, etcd permissions, controller manager settings.

That is the catch on a managed cluster. You do not control the API server flags, and the provider does not expose the files kube-bench wants to read. Many checks will be marked as not applicable or will fail for reasons you cannot act on. Use the managed-cluster-specific benchmark version where one exists, and be explicit with your team that the control plane section is the provider's responsibility, documented in the shared responsibility model rather than in your backlog.

Kubescape takes a broader view: benchmark controls plus workload configuration, plus mappings to attack frameworks and regulatory control sets, with image scanning and admission integration. It is more useful as a single view of cluster posture, and correspondingly noisier out of the box.

Both belong in the same set as the tools in eight open-source tools for cloud posture. Neither is a substitute for the others: scanning is static, admission control prevents, and runtime detection observes, which is the layering set out in Falco tells you what a container did.

The six findings that are always there

After enough clusters, the list stops surprising you. These six account for most of the real risk in the report.

1. Containers running as root. The default when nobody specifies otherwise. A container escape from a root process reaches the node with root. The fix is a security context with a non-root user, a read-only root filesystem and dropped capabilities, and it usually requires a change to the image rather than only the manifest.

2. Privileged containers and host namespace sharing. A privileged container is effectively root on the node. Host network, host PID and host path mounts are the same category. Every estate has a few, usually a monitoring agent or a legacy workload, and each one needs either a justification recorded or removal.

3. No network policy. Every pod can reach every other pod in every namespace by default, which makes lateral movement trivial after any single compromise. This is the highest-value fix on the list and the one covered in several teams on one cluster.

4. Over-permissive RBAC. Cluster-admin bound to a group nobody has reviewed, wildcards in roles, service accounts with more than they need. Pay particular attention to permission to read secrets and to create pods, since the second implies the first.

5. Automounted service account tokens. Mounted by default into every pod, whether or not the workload calls the Kubernetes API. Most do not. Disabling the automount where it is unnecessary removes a credential an attacker would otherwise find immediately.

6. Access to the cloud metadata endpoint. Not a Kubernetes control and the most consequential of all. From a compromised pod, reaching the node's metadata endpoint is the classic route to cloud credentials. Block it with a network policy and use workload identity federation instead, as in a Kubernetes Secret is base64.

Fix those six and the risk profile of the cluster changes more than the finding count suggests.

Making the report actionable

The reason posture scanning fails is presentation, not detection.

Filter by exploitability, not by severity label. A high-severity finding on a workload with no network exposure and no sensitive data matters less than a medium one on your internet-facing service. Enrich findings with whether the workload is exposed and what it can reach.

Group by fix, not by finding. Three hundred findings frequently resolve to eight changes, because the same base image or the same Helm chart produces the same finding across every namespace. Presenting eight tasks gets work done; presenting three hundred findings does not.

Assign by namespace owner. A report to the platform team is a report to people who cannot change most of the workloads. The ownership metadata that makes this possible is the same as in a developer portal is only as good as its catalogue.

Suppress with a reason and an expiry. An accepted risk is legitimate. An accepted risk with no owner, no justification and no review date is a permanent blind spot.

Track one number: the count of findings in the six categories above, over time. Not the total, which moves for irrelevant reasons.

Scan continuously, and shift the fix left

A quarterly scan tells you the state on the day of the scan. Clusters change daily.

Run it in CI against manifests and Helm charts, so a workload is checked before it exists. Most of the six findings above are visible in the manifest, which means they can be caught at review time rather than in a report afterwards.

Then run it continuously in the cluster for what only shows up at runtime: RBAC bindings created by hand, workloads deployed outside the pipeline, and drift.

And once the backlog is cleared, enforce with admission control so the finding cannot recur, which is the audit-then-warn-then-enforce sequence in Kyverno or Gatekeeper. Pod Security Admission at the restricted level covers a large share of these six on its own and needs no extra controller.

Compliance mappings, used carefully

These tools map findings to control sets, which is genuinely useful for evidence and dangerous as a target.

Useful: an auditor asking how you enforce container hardening gets a scan result, a policy that enforces it and a history of both, which feeds the model in one control set across frameworks.

Dangerous: a compliance percentage becomes the goal, and the fastest way to raise it is suppressing findings rather than fixing them. The score is an indicator, not an objective, for the same reason set out in secure score is not the goal.

The things people forget

  • The scanner needs privileges. It reads cluster configuration and sometimes node files, which makes it a sensitive workload in its own right.
  • Not applicable is a real result. On managed clusters, document which sections belong to the provider so they stop appearing as failures.
  • Findings without context mislead. The same misconfiguration on an internal batch job and on a public API are not the same risk.
  • Helm chart defaults are the root cause. Fixing a chart fixes every release of it, which is why grouping by fix works.
  • Scanning does not cover the supply chain. The image contents are a separate question, covered in Trivy and Grype.

What to do this week

Run one query rather than a full scan: list every pod in production running as root, and every pod with the service account token automounted that never calls the Kubernetes API. Those two lists are short, actionable and cover two of the six. Fixing them is a manifest change per workload and it measurably reduces what a compromise is worth. We start the cluster hardening workstream of a security engagement with exactly those two lists.

ConsultorIA

Want this done on your cloud?

A ten-day read-only assessment is free, and Skyline lets you see your estate on a map before you write to us.

Related articles