The OWASP Kubernetes Top 10 was published. Security teams nodded. Engineers bookmarked it. And then approximately nothing changed in most clusters.
Because knowing about a vulnerability and actually fixing it are two very different things. This article is about the second one.
We're going through all 10. With real examples, real misconfigurations, and what you can actually do about each one today.
π€ Why This List Still Matters in 2026
Because the same misconfigurations that were listed two years ago are still showing up in production clusters. I know because I've audited them. Secrets in environment variables. Pods running as root. No network policies anywhere. RBAC so permissive it might as well not exist.
The OWASP list isn't a warning about exotic attacks. It's a list of mistakes that real engineers make under deadline pressure, that stay in place for years because nobody goes back to tighten things up.
π K01 — Insecure Workload Configurations
The most common entry point. Pods running as root, with privileged access, no read-only filesystem, no seccompProfile. Every single one of these is a foothold for an attacker who gets past your container boundary.
# What a hardened pod spec looks like
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault
π None of that should be optional. All of it should be your baseline. Use OPA Gatekeeper or Kyverno to enforce it at admission so nothing sneaks in.
π K02 — Supply Chain Vulnerabilities
You're not just running your code. You're running your base image, plus its dependencies, plus the OS layer underneath it. Any one of those layers can be compromised.
Sign your images. Scan them on push. Verify signatures at admission. Three steps most teams skip entirely.
# Enforce only signed images via Kyverno policy
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce
rules:
- name: check-image-signature
match:
resources:
kinds: ["Pod"]
verifyImages:
- imageReferences:
- "registry.company.com/*"
attestors:
- entries:
- keyless:
subject: "https://github.com/your-org/*"
π K03 — Overly Permissive RBAC
"Give them cluster-admin for now, we'll tighten it later." Every cluster has this debt. Nobody ever goes back. Least privilege is not a principle most teams actually apply — it's a principle most teams intend to apply eventually.
# Instead of this
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin # never do this for app service accounts
# Do this — namespace-scoped, specific verbs only
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: app-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods", "configmaps"]
verbs: ["get", "list", "watch"]
π Audit your bindings right now: kubectl get clusterrolebindings -o wide | grep cluster-admin. Whatever you see will probably surprise you.
π K04 — Lack of Centralized Policy Enforcement
Individual namespace-level configs are not policy enforcement. They're hopes. Real enforcement means every Pod creation goes through an admission controller that validates against your security requirements — before it ever runs.
OPA Gatekeeper and Kyverno both do this. Pick one. Deploy it. Write policies. It's uncomfortable until it's the thing that stops a misconfigured pod from going to prod.
π K05 — Inadequate Logging and Monitoring
If you can't tell me which service account ran kubectl exec into a production pod at 3am on Wednesday, you have an audit logging gap. Not a Kubernetes gap — a business and compliance gap.
# Enable audit logging in your API server config
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
Then ship those logs somewhere you can actually query them. They're useless sitting on the API server disk.
π K06 — Broken Authentication Mechanisms
Long-lived service account tokens. Static kubeconfig files distributed across the team. No rotation policy. These are all authentication failures waiting for the right moment.
π Use IRSA (IAM Roles for Service Accounts) on EKS. Token expiry should be 24 hours max. Kubeconfigs should be generated on demand, not committed anywhere.
π K07 — Missing Network Segmentation
By default, every pod in your cluster can talk to every other pod. Every namespace. Every service. No boundaries. An attacker who compromises one pod has a free internal network tour.
Network Policies are the fix. Most teams don't have them. We cover this in depth in our Network Policies article — but the short version: start with a default-deny and add explicit allows.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
π K08 — Secrets Management Failures
Kubernetes Secrets are base64 encoded. Not encrypted. Not secret by any meaningful definition of the word unless you've added encryption at rest and a proper external secrets manager.
We have a full article on this. The short version: External Secrets Operator + AWS Secrets Manager (or Vault). Don't put production credentials in a Kubernetes Secret object and call it done.
π K09 — Misconfigured Cluster Components
etcd exposed without TLS. API server with anonymous auth enabled. Kubelet read-only port open. These are misconfigurations in the cluster control plane itself, not your workloads.
# Run kube-bench to check your control plane
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
kubectl logs -l app=kube-bench
π kube-bench implements the CIS Kubernetes Benchmark checks. Run it. Fix the HIGH severity findings first.
π K10 — Outdated and Vulnerable Components
Running Kubernetes 1.25 in prod while 1.30 is available isn't just a features problem. Every minor version is also a security patch. The attack surface of an old cluster is documented, public, and indexed by automated scanners.
Set a quarterly upgrade cadence minimum. Two versions behind is your absolute maximum. One version behind is where you want to live.
⚠️ The Honest Reality
You probably have issues from at least six of these ten in your cluster right now. That's not a judgment — it's just the statistical reality of every production Kubernetes environment I've touched. The goal isn't perfection on day one. It's systematic improvement, one risk at a time, starting with whatever is most exposed.
π Continue Your CloudChef Journey
π References
π Final Thoughts
The OWASP Top 10 isn't a scary list. It's a checklist. Work through it in order of risk for your specific environment. Start with what's most exposed. Automate enforcement where you can. And remember — every one of these was an "we'll fix it later" that never got fixed.
π Later is now a good time.
No comments:
Post a Comment