Safeguard
Security Guides•

How to set a default deny NetworkPolicy in Kubernetes

Pods accept all traffic until a policy selects them. Add a default deny per namespace, then allow only what each app needs. Includes YAML and pitfalls.

Safeguard Security Team
3 min read

Without any NetworkPolicy, every pod can send and receive traffic from every other pod. To fix that, create a policy in each namespace with an empty podSelector and the policy types you want blocked, then add narrow allow rules. This only works if your network plugin enforces NetworkPolicy.

Check your plugin first

NetworkPolicies are enforced by the cluster's network plugin. The Kubernetes docs say that creating a policy without a controller that implements it has no effect. Calico, Cilium and Antrea are among the plugins listed as supporting it. Before you rely on policies, test one: apply a deny rule and confirm a connection actually fails.

The default behavior

A pod is non-isolated for ingress and egress by default, so all connections are allowed. A pod becomes isolated in a direction when a policy selects it and lists that direction in policyTypes. After that, only traffic allowed by some policy's rules gets through.

Policies are additive. If several apply to a pod, the allowed traffic is the union of their rules, and order does not matter.

The default deny manifests

Deny all ingress in a namespace:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Deny all egress is the same with Egress as the policy type. To deny both, list both types.

An empty podSelector selects every pod in the namespace. Apply one of these to each application namespace, ideally from a template so new namespaces get it automatically.

Adding allow rules

A connection from pod A to pod B needs both A's egress policy and B's ingress policy to allow it. If you deny egress, remember that pods usually need to reach cluster DNS. Add an explicit egress allow for your DNS service, or name resolution will break and the failure will look unrelated.

Build allow rules from labels and namespaces, not IP addresses, so they survive rescheduling. Start with the paths you can name: frontend to API, API to database, and ingress controller to frontend.

Limits to know

NetworkPolicy works on pod labels, namespace labels and IP blocks. It is not a layer seven control, and logging or TLS rules depend on the plugin rather than the core API. Policies are namespaced, so there is no built-in cluster-wide rule in the core API. Verify details in your plugin's documentation.

Policy files like these belong in version control and code review, the same as application code.

Testing that it works

After applying a deny policy, test from a temporary pod in the same namespace with a command such as a short curl or wget against another service. It should fail or time out. Then apply your allow rule and test again. Run the same check from a pod in another namespace to confirm cross-namespace traffic is blocked as intended.

Keep these checks in a script and run them after network plugin upgrades, since enforcement depends on the plugin.

Quick check

If I deny ingress, does egress also get blocked?

No. Each direction is isolated only if listed in policyTypes.

Why did DNS stop working after deny egress?

Pods are now isolated for egress, so lookups to the DNS service need an explicit allow rule.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.