Minimize The Admission Of Containers Which Use HostPorts
More Info:
HostPorts bind container ports directly to the node, bypassing network policy and exposing services on the host. Restrict their use.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify current workloads using
hostPort- Run on: any machine with
kubectlaccess - Command:
kubectl get pods -A -o jsonpath='{range .items[?(@.spec.containers[*].ports[*].hostPort)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'
- Save/record this list as the baseline of current
hostPortusage.
- Run on: any machine with
-
Review each identified pod’s necessity for
hostPort- For each
NAMESPACE/PODfrom step 1:kubectl get pod POD -n NAMESPACE -o yaml > POD-NAMESPACE.yaml - Manually inspect:
- Which containers/ports use
hostPortand on which nodes. - Whether they front internet-facing or sensitive services.
- Whether equivalent access could be provided via ClusterIP/LoadBalancer/Ingress instead of
hostPort.
- Which containers/ports use
- Decide for each: “required (documented justification)” or “can be removed/avoided”.
- For each
-
Review and design Pod Security / admission policy per namespace
- For each namespace that runs user workloads (and especially those with unjustified
hostPortuse):- If using built-in Pod Security Admission, check labels:
kubectl get ns NAMESPACE --show-labels
- Assess whether the effective Pod Security level (e.g.,
baseline,restricted) and any custom admission policies already limithostPort.
- Assess whether the effective Pod Security level (e.g.,
- If using another admission controller (e.g., Kyverno, OPA Gatekeeper), list policies that affect
hostPortin that namespace using your policy tool (no generickubectlcommand exists; follow your policy system’s CLI/docs).
- If using built-in Pod Security Admission, check labels:
- For each namespace that runs user workloads (and especially those with unjustified
-
Implement or tighten admission policy to restrict
hostPort- Decide per namespace:
- Namespaces where
hostPortshould be disallowed except for cluster-operator-approved workloads. - Namespaces where
hostPortis temporarily allowed but must be minimized.
- Namespaces where
- Apply or update your admission policy mechanism accordingly (Pod Security Admission level, Kyverno/Gatekeeper rules, or other). Document any namespace-specific exceptions and which service accounts / labels are allowed to use
hostPort. - This step is policy- and environment-specific; there is no single
kubectlcommand that enforces it generically.
- Decide per namespace:
-
Refactor or remove non-essential
hostPortusage- For pods marked “can be removed/avoided” in step 2:
- Update their Deployment/DaemonSet/StatefulSet/Pod manifests (in Git/IaC or via
kubectl editif appropriate) to removehostPortfields and use Services/Ingress instead. - Reapply manifests using your standard deployment process, for example:
kubectl apply -f UPDATED-MANIFEST.yaml
- Update their Deployment/DaemonSet/StatefulSet/Pod manifests (in Git/IaC or via
- Ensure any required firewall or ingress changes are made so functionality is preserved without
hostPort.
- For pods marked “can be removed/avoided” in step 2:
-
Verify minimized
hostPortusage and effective restriction- Re-run the discovery from step 1:
kubectl get pods -A -o jsonpath='{range .items[?(@.spec.containers[*].ports[*].hostPort)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'
- Confirm that:
- Only the few, explicitly justified workloads still appear.
- Creating a test pod with
hostPortin a restricted namespace is rejected by admission (use a small test manifest andkubectl apply -f test-hostport.yamlto confirm it is denied).
- Re-run the discovery from step 1:
Using kubectl
# 1) List all pods that request hostPorts in all namespaces
# Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o=jsonpath='{range .items[?(@.spec.containers[*].ports[*].hostPort)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{end}'
Problem indication:
Any line of output means that pod uses at least one hostPort. Each such pod must be manually reviewed to decide if hostPort is justified.
# 2) Show details of pods using hostPorts so you can review them
# Run on: any machine with kubectl access
kubectl get pods --all-namespaces -o json \
| jq '.items[]
| select(.spec.containers[].ports[]? | has("hostPort"))
| {
namespace: .metadata.namespace,
name: .metadata.name,
nodeName: .spec.nodeName,
containers: [.spec.containers[]
| {
name,
ports: [.ports[]? | select(has("hostPort"))]
}
]
}'
Problem indication:
Look for:
- Unnecessary
hostPortuse (e.g.,80,443,22, or wide port ranges) where a Service/Ingress/LoadBalancer would suffice. hostPorton multi-tenant or shared nodes.
Any such cases are candidates for remediation.
# 3) List NetworkPolicies that attempt to control hostPorts (for context)
# Note: NetworkPolicies do NOT govern hostPorts, but this shows current intent
# Run on: any machine with kubectl access
kubectl get networkpolicy --all-namespaces -o wide
Problem indication:
If you see NetworkPolicies that appear to “lock down” traffic but many workloads use hostPort, be aware that those policies do not protect the host-bound ports. This is an architectural risk to review.
# 4) Discover namespaces with user workloads but no admission policies defined
# (to identify where you may need to add policies restricting hostPorts)
# Run on: any machine with kubectl access
echo "Namespaces with pods:" && \
kubectl get pods --all-namespaces --no-headers | awk '{print $1}' | sort -u
echo
echo "Namespaces with LimitRanges (resource policies, FYI):" && \
kubectl get limitrange --all-namespaces --no-headers 2>/dev/null | awk '{print $1}' | sort -u
echo
echo "Namespaces with NetworkPolicies:" && \
kubectl get networkpolicy --all-namespaces --no-headers 2>/dev/null | awk '{print $1}' | sort -u
Problem indication:
Namespaces appearing in “Namespaces with pods” but lacking any security/admission-related policy (and that also contain pods using hostPort from step 1/2) should be prioritized for adding policy to restrict hostPort usage.
# 5) For a specific namespace, inspect all pod specs for hostPort usage
# Replace NAMESPACE with the namespace you are reviewing.
# Run on: any machine with kubectl access
NAMESPACE=default
kubectl get pods -n "$NAMESPACE" -o yaml \
| yq '.items[]
| select(.spec.containers[].ports[]? | has("hostPort"))
| {
name: .metadata.name,
nodeName: .spec.nodeName,
containers: [.spec.containers[]
| {
name,
ports: [.ports[]? | select(has("hostPort"))]
}
]
}'
Problem indication:
If a namespace is intended to be “locked down” or multi-tenant but this output shows many pods with hostPort, the risk is higher and manual remediation is recommended (redesign to use Services, adjust placement, or introduce admission policy).
Automation
#!/usr/bin/env bash
#
# Report all Pods and workload templates that use hostPort across the cluster.
# Run on any machine with kubectl access and current-context set to the target cluster.
set -euo pipefail
echo "=== HostPort usage report (live Pods) ==="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| (
.spec.containers[]?,
.spec.initContainers[]?
)
| select(.ports != null)
| .ports[]?
| select(.hostPort != null and .hostPort != 0)
| "\($pod.metadata.namespace)\t\($pod.metadata.name)\t\($pod.spec.nodeName // "N/A")\t\(.name // "N/A")\t\(.containerPorts // .containerPort // "N/A")\t\(.hostPort)"
' 2>/dev/null \
| awk 'BEGIN { printf "NAMESPACE\tPOD\tNODE\tCONTAINER\tCONTAINER_PORT\tHOST_PORT\n" } 1'
echo
echo "=== HostPort usage report (workload specs: Deployments, DaemonSets, StatefulSets, Jobs, CronJobs, ReplicaSets, ReplicationControllers) ==="
kubectl get deploy,ds,sts,job,cronjob,rs,rc --all-namespaces -o json \
| jq -r '
.items[]
| . as $w
| (
.spec.template.spec.containers[]?,
.spec.template.spec.initContainers[]?
)
| select(.ports != null)
| .ports[]?
| select(.hostPort != null and .hostPort != 0)
| "\($w.kind)\t\($w.metadata.namespace)\t\($w.metadata.name)\t\(.name // "N/A")\t\(.containerPorts // .containerPort // "N/A")\t\(.hostPort)"
' 2>/dev/null \
| awk 'BEGIN { printf "KIND\tNAMESPACE\tNAME\tCONTAINER\tCONTAINER_PORT\tHOST_PORT\n" } 1'
echo
echo "=== Summary: total objects using hostPort per namespace (live Pods) ==="
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| select(
(
.spec.containers[]? | .ports[]? | (.hostPort // 0)
) != 0
or
(
.spec.initContainers[]? | .ports[]? | (.hostPort // 0)
) != 0
)
| .metadata.namespace
' \
| sort | uniq -c | sort -nr \
| awk 'BEGIN { printf "COUNT\tNAMESPACE\n" } { print }'
How to interpret the output
- Any line where
HOST_PORT(for Pods or workloads) is a non-zero value indicates a potential policy violation that must be reviewed. - Pay particular attention to:
- User/application namespaces (e.g., not
kube-system,kube-public,kube-node-lease). - HostPorts exposed on broad or privileged workloads (e.g., internet-facing services, DaemonSets).
- User/application namespaces (e.g., not
- Namespaces with non-zero
COUNTin the summary should have admission policies (e.g., Pod Security Admission or Admission Webhooks) evaluated or added to restrict or justify hostPort usage.
This script only reports; creating or tightening admission policies must be done manually based on your risk posture and any legitimate need for hostPorts.