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

NetworkPolicy Objects Your CNI Silently Ignores

Severity
high
Reviewed
13 Jul 2026
Remediation
~20 minutes
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.

Operational summary

At a glance

Symptom
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…
Likely cause
NetworkPolicy resources are accepted and stored by the API server even when the underlying CNI plugin implements no enforcement for them.
Impact
Unrestricted east-west traffic lets one compromised pod reach every database, service, and namespace in the cluster despite documented network policies.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Verify CNI enforcement capability before relying on NetworkPolicy, and run conformance testing such as Cyclonus in CI to confirm policies actually block traffic.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

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.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

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")]}'
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources