Skip to main content

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

Manual Steps
  1. Identify current workloads using hostPort

    • Run on: any machine with kubectl access
    • 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 hostPort usage.
  2. Review each identified pod’s necessity for hostPort

    • For each NAMESPACE/POD from step 1:
      kubectl get pod POD -n NAMESPACE -o yaml > POD-NAMESPACE.yaml
    • Manually inspect:
      • Which containers/ports use hostPort and on which nodes.
      • Whether they front internet-facing or sensitive services.
      • Whether equivalent access could be provided via ClusterIP/LoadBalancer/Ingress instead of hostPort.
    • Decide for each: “required (documented justification)” or “can be removed/avoided”.
  3. Review and design Pod Security / admission policy per namespace

    • For each namespace that runs user workloads (and especially those with unjustified hostPort use):
      • 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 limit hostPort.
      • If using another admission controller (e.g., Kyverno, OPA Gatekeeper), list policies that affect hostPort in that namespace using your policy tool (no generic kubectl command exists; follow your policy system’s CLI/docs).
  4. Implement or tighten admission policy to restrict hostPort

    • Decide per namespace:
      • Namespaces where hostPort should be disallowed except for cluster-operator-approved workloads.
      • Namespaces where hostPort is temporarily allowed but must be minimized.
    • 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 kubectl command that enforces it generically.
  5. Refactor or remove non-essential hostPort usage

    • For pods marked “can be removed/avoided” in step 2:
      • Update their Deployment/DaemonSet/StatefulSet/Pod manifests (in Git/IaC or via kubectl edit if appropriate) to remove hostPort fields and use Services/Ingress instead.
      • Reapply manifests using your standard deployment process, for example:
        kubectl apply -f UPDATED-MANIFEST.yaml
    • Ensure any required firewall or ingress changes are made so functionality is preserved without hostPort.
  6. Verify minimized hostPort usage 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 hostPort in a restricted namespace is rejected by admission (use a small test manifest and kubectl apply -f test-hostport.yaml to confirm it is denied).
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 hostPort use (e.g., 80, 443, 22, or wide port ranges) where a Service/Ingress/LoadBalancer would suffice.
  • hostPort on 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).
  • Namespaces with non-zero COUNT in 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.