Back to Cheat Sheets

🛡️ Lack of Centralized Policy Enforcement

OWASP Kubernetes Top 10 - K04

HIGH RISK

📋 What Is It?

Lack of Centralized Policy Enforcement is the absence of a consistent, automated control point that validates every workload against your security rules before it runs - and keeps validating as the cluster changes. A default Kubernetes cluster admits a privileged, root, host-mounting pod pulling an unsigned image without complaint. This is the meta-failure: the reason individual mistakes (K01, K03) reach production is that no engine sits in the admission path saying "no." When enforcement is missing, inconsistent, or stuck in audit-only mode, security depends on every developer remembering every rule on every manifest.

K04 OWASP Rank
Admission Focus Area
Medium To Prevent

⚠️ Common Exploits

  • Canary Privileged Pod: Submitting one privileged: true pod confirms whether the cluster enforces anything at all
  • Read the Config: Listing webhook configs and namespace PSA labels reveals unguarded namespaces directly
  • Unlabeled Namespace: prod is locked down but default/sandbox/legacy are wide open
  • Audit/Warn-Only: Policies that only log or warn admit the pod anyway - the warning is noise, not a control
  • Fail-Open Webhook: failurePolicy: Ignore turns a policy-engine outage into an enforcement bypass
  • Untrusted Image: With no registry/signature policy, provenance is never checked and poisoned images run
  • Bypass Review: Direct kubectl apply, Helm, and operators sail past pull-request checks

🔴 Attack Flow

1. Probe: try to create a trivial privileged pod
↓
2. Map gaps: unguarded? audit-only? fail-open?
↓
3. Deploy the workload that should have been blocked
↓
4. Escape: chroot to node, read kubelet kubeconfig
↓
5. IMPACT: Node to cluster-admin, no CVE needed!

❌ Vulnerable Code

# Bad: a fresh cluster with no PSA labels and no policy engine # admits this dangerous manifest without evaluating it at all apiVersion: v1 kind: Pod metadata: name: builder namespace: default # no pod-security.kubernetes.io/enforce label spec: hostPID: true # host process namespace containers: - name: c image: anon-registry.io/tools:latest # unapproved, unsigned image securityContext: privileged: true # full host capabilities volumeMounts: - { name: host, mountPath: /host } volumes: - name: host hostPath: { path: / } # entire node filesystem # $ kubectl apply -f builder.yaml # pod/builder created <- admitted; nothing evaluated it # Bad: namespace labeled warn-only -> a K04 trap, still ADMITS labels: pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/audit: restricted # No 'enforce' label == no blocking # Bad: webhook fails open failurePolicy: Ignore # engine down == workloads admitted unchecked

✅ Secure Code

# Good: enforce restricted PSA, plus a cluster-wide default for new namespaces apiVersion: v1 kind: Namespace metadata: name: payments labels: pod-security.kubernetes.io/enforce: restricted # actually BLOCKS pod-security.kubernetes.io/enforce-version: latest pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/audit: restricted # Good: Kyverno ClusterPolicy in Enforce mode (deny, not audit) apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: pod-security-guardrails spec: validationFailureAction: Enforce # Enforce = deny (NOT Audit) background: true # also flags pre-existing violations rules: - name: disallow-privileged match: { any: [{ resources: { kinds: [Pod] } }] } validate: message: "Privileged containers are not allowed." pattern: spec: containers: - =(securityContext): =(privileged): "false" # Good: webhook fails closed so an outage cannot disable policy failurePolicy: Fail # if policy cannot be consulted, DENY

✓ Prevention Checklist

  • Set Pod Security Admission to enforce (restricted floor) on every namespace
  • Apply a cluster-wide PSA default so new namespaces aren't born unguarded
  • Deploy a policy engine (Kyverno / OPA Gatekeeper) in enforce/deny mode
  • Use mutating policy to inject safe defaults (secure securityContext)
  • Enforce image provenance - approved registries and signature verification
  • Require resource limits and standard labels at admission
  • Configure sensitive webhooks to fail closed (failurePolicy: Fail)
  • Source all policy from Git and reconcile to all clusters (GitOps)
  • Validate policies in CI before merge (kyverno apply, conftest)
  • Run continuous conformance scanning (kube-bench, Polaris, kubescape)
  • Adopt PSA/policy engine before upgrading past 1.25 (PSP removed)

🔍 Detection & Tools

Policy Engines & Baseline:

Kyverno OPA/Gatekeeper Pod Security Admission conftest

Conformance Scanning:

kube-bench Polaris kubescape Trivy

How to Test:

  • Deploy a canary privileged pod - is it denied or created?
  • Check for webhooks: kubectl get validatingwebhookconfigurations
  • Audit which namespaces have a pod-security.kubernetes.io/enforce label
  • Confirm policies are Enforce/deny, not Audit/warn
  • Check failurePolicy on sensitive webhooks (must be Fail)

🌍 Real-World

  • Exposed management plane leading to cryptojacking: An unauthenticated dashboard/kubelet/API endpoint plus no admission policy lets an attacker or botnet deploy a cryptominer - the management-plane-plus-no-guardrails shape of the well-publicised cloud Kubernetes console cases.
  • Container escape via a workload that should never have been admitted: A privileged, hostPath, or hostPID pod breaks out to the node; a restricted PSA profile or Kyverno/Gatekeeper rule would have rejected the manifest at admission.
  • Silent drift after PSP removal: A cluster upgraded to 1.25+ loses PodSecurityPolicy with no PSA or policy engine adopted first; previously-blocked workloads are admitted freely for weeks until an audit surfaces it.
  • Note: These are documented incident classes, described generically. The default cluster ships without centralized enforcement, so the vulnerable state is the one you get unless you deliberately build the guardrails.

📌 Quick Tips

  • DO NOT assume Kubernetes blocks dangerous pods by default
  • DO NOT leave policies in audit/warn mode
  • DO NOT configure sensitive webhooks to fail open
  • DO enforce PSA restricted on every namespace
  • DO run a policy engine in enforce mode
  • DO source policy from Git and apply it everywhere
  • DO scan continuously for drift

📜 Compliance

Related Standards:

  • CIS Kubernetes Benchmark - Policies
  • NSA/CISA Kubernetes Hardening - Admission Control
  • Pod Security Standards baseline / restricted
  • SOC 2 CC7.1 - Detection of Deviations
  • PCI-DSS Requirement 2.2 - Secure Configuration