Skip to main content
KBY Technologies Logo
cd ../config-traps
risk/register/networkpolicy-objects-your-cni-silently-ignores.html
Kubernetes Networkinghigh severityKubernetes

NetworkPolicy Objects Your CNI Silently Ignores

Overview

A cluster can carry fully written NetworkPolicy manifests, show them as Synced in ArgoCD, and still route every pod's traffic unrestricted across namespaces, because the API server stores these objects whether or not the installed CNI actually enforces them. Standard audits rarely distinguish a stored policy from an enforced one, so the gap on Kubernetes clusters surfaces only after a compromised pod reaches the database tier directly.

At a glance

Unsafe setting
NetworkPolicy resources are accepted and stored by the API server even when the underlying CNI plugin implements no enforcement for them.
Failure trigger
A cluster runs without a policy-enforcing CNI (Calico, Cilium, or an enabled VPC CNI policy agent), so applied NetworkPolicy objects are silently treated as no-ops.
Blast radius
Unrestricted east-west traffic lets one compromised pod reach every database, service, and namespace in the cluster despite documented network policies.
Recommended control
Verify CNI enforcement capability before relying on NetworkPolicy, and run conformance testing such as Cyclonus in CI to confirm policies actually block traffic.

Fix commands and configuration

kubectl get pods -n kube-system -l k8s-app=calico-node
gcloud container clusters describe CLUSTER --format='value(addonsConfig.networkPolicyConfig)'
kubectl get daemonset aws-node -n kube-system -o jsonpath='{.spec.template.spec.containers[?(@.name=="aws-network-policy-agent")]}'

The Trap

Kubernetes accepts and persists NetworkPolicy objects through admission and schema validation regardless of whether the cluster’s CNI plugin implements any enforcement logic. The resource has no status subresource and no condition field reporting whether traffic is actually being filtered. A kubectl apply that returns success, and a kubectl get networkpolicy that lists the object, tell you nothing about whether a single packet has ever been dropped because of it.

The Default State

GKE clusters created without --enable-network-policy ship with no policy engine at all; the flag is immutable post-creation and requires a node pool rebuild to retrofit. EKS clusters running the default aws-vpc-cni without the network policy agent enabled (pre-1.25 behaviour, or the add-on left at its default configuration) accept NetworkPolicy manifests as inert YAML. kubeadm clusters bootstrapped with flannel behave identically, since flannel has no policy controller. In every one of these cases the control plane, CI pipeline, and GitOps tool all report a healthy, synced, compliant state.

The Blast Radius

Security teams treat the presence of NetworkPolicy manifests in the repository as evidence of segmentation for CIS Benchmark 5.3.2 or PCI-DSS scope reduction, when no enforcement exists. East-west traffic between namespaces, tiers, and tenants remains completely open. Once one pod is compromised via a vulnerable dependency or an exposed debug endpoint, it reaches every database pod, internal API, and metrics endpoint in the cluster directly, with no policy anywhere in the traffic path actually inspecting the connection. Incident response assumes segmentation contained the blast radius; it did not, because the containment never existed outside the YAML file.

The Lead Mechanic Fix

Confirm enforcement before trusting any policy. Check for a running policy-enforcing DaemonSet: kubectl get pods -n kube-system -l k8s-app=calico-node or the Cilium equivalent. On GKE, verify with gcloud container clusters describe CLUSTER --format='value(addonsConfig.networkPolicyConfig)'. On EKS, confirm the VPC CNI network policy agent is enabled via kubectl get daemonset aws-node -n kube-system -o jsonpath='{.spec.template.spec.containers[?(@.name=="aws-network-policy-agent")]}'. Deploy Calico or Cilium as the enforcing CNI if absent, apply a namespace-scoped default-deny baseline (podSelector: {}, no ingress/egress rules), and run the Cyclonus conformance suite against the cluster in CI to prove policies actually block disallowed flows before merging.