Skip to main content
security · kubernetes

Services of type NodePort outside dev and test

resource types
1
rule IDs covered
3
severity
medium

What does ZopNight detect here?

ZopNight flags an EKS, GKE or AKS Service of `type: NodePort` unless labels, namespace or naming mark it as dev or test. Kubernetes opens the allocated port, drawn from 30000-32767 by default, on every node, so the Service answers on node IP addresses wherever firewall rules let traffic in, outside any Ingress routing or TLS.

Signal and threshold

How ZopNight evaluates Services of type NodePort outside dev and test.
Field Value
Rule IDsRC-1722 · RC-1822 · RC-1922
Categorysecurity
Severitymedium
Metricspec.type
ThresholdNodePort, not dev or test by label, namespace or name
SourceZopNight
Permissions usedlist services

The same port, open on every node

With type: NodePort, the control plane allocates a port from the range set by --service-node-port-range, 30000-32767 by default, and each node proxies that port into the Service. The Service documentation adds that in kube-proxy’s iptables mode the port is available on all node IPs, while nftables mode limits it to the node’s primary IP by default. Either way the Service is reachable directly on node addresses, next to rather than behind whatever Ingress, TLS or authentication you run.

That leaves node firewalls as the main control. Security groups or firewall rules written for other purposes may already admit the node-port range, and a single overly broad rule exposes every NodePort Service in the cluster at once.

Listing NodePort Services and their ports

Terminal window
kubectl get services -A -o json | jq -r '
.items[]
| select(.spec.type == "NodePort")
| "\(.metadata.namespace)/\(.metadata.name) nodePorts=\([.spec.ports[].nodePort] | join(","))"'

Compare those ports with the inbound rules on your node security groups or firewall.

How ZopNight picks which NodePorts to flag

The rule fires on Services whose recorded type is NodePort, then applies the same context test used for LoadBalancer Services. An environment label (env, environment, stage or tier) set to a production value keeps the Service flagged regardless of its name. Without one, a dev or test label, a namespace segment such as dev, development, test, testing, qa, staging, stage, sandbox or demo, or a name segment matching those words or canary, preview or experiment, suppresses it, since node ports are a common shortcut for ad-hoc access in non-production.

Services that fall outside it

LoadBalancer Services also open node ports by default, but they are reported under Service type LoadBalancer, not here. ClusterIP and ExternalName Services are never flagged. The check reads only the type, labels, namespace and name; it does not inspect your firewall rules, so it cannot tell whether a port is actually reachable from outside.

Medium severity, no saving

No dollar amount is attached. The risk is an unauthenticated, unencrypted path to a workload that bypasses the controls your Ingress layer was built to enforce.

Closing the node port

  1. Confirm who connects to the node port and from where.
  2. Change type to ClusterIP for traffic that stays inside the cluster.
  3. Publish external HTTP traffic through an Ingress with TLS, as Ingress without TLS explains.
  4. If a node port must stay, restrict the node firewall or security group to known sources, and consider kube-proxy’s --nodeport-addresses flag to limit which node IPs listen.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·