Skip to main content

Minimize Admission Of Containers HostPorts

More Info:

Do not generally permit containers which require the use of HostPorts.

Risk Level

Low

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Identify all pods 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}{"\n"}{end}'
      For more detail:
      kubectl get pods -A -o json | jq '.items[]
      | select(.spec.containers[].ports[]? | has("hostPort"))
      | {ns:.metadata.namespace,name:.metadata.name,ports:[.spec.containers[].ports[]?|select(has("hostPort"))]}'
  2. Review business / technical necessity of each hostPort use

    • For each pod found, inspect its spec and discuss with the owning team whether hostPort is strictly required (e.g., legacy daemon, node-local listener):
      kubectl -n <NAMESPACE> get pod <POD_NAME> -o yaml
    • Classify each as: “Required and justified” or “Not required / can be redesigned”.
  3. Design namespace-level policy for hostPort

    • For namespaces where hostPort is not needed at all, plan a policy that denies any hostPort.
    • For namespaces where a few workloads must use hostPort, plan a policy that only allows specific ports or labels and denies all other hostPort use.
    • Decide which admission control mechanism you will use (e.g., built‑in PodSecurity admission with restricted profiles plus an external policy engine like Kyverno / Gatekeeper, or just the external policy engine).
  4. Implement or update the admission policies for each namespace

    • Example: label namespace to use a restrictive Pod Security level (if compatible with workloads):
      kubectl label namespace <NAMESPACE> pod-security.kubernetes.io/enforce=restricted --overwrite
    • Then add or adjust your chosen policy engine’s rules (Kyverno/OPA Gatekeeper/etc.) so that, in the target namespaces, pods with any container ports.hostPort are denied, or only allowed per your design. (This step is policy‑engine specific and must be done by editing/creating its ClusterPolicy/Constraint manifests and applying them with kubectl apply -f <FILE>.yaml.)
  5. Refactor workloads that should not use hostPort

    • For each pod classified as “Not required / can be redesigned”, modify its Deployment/DaemonSet/Pod manifest to remove hostPort from all container ports and rely on Services, NodePorts, or Ingress instead:
      kubectl -n <NAMESPACE> edit <KIND> <NAME>
    • Or update the manifest in version control and apply:
      kubectl apply -f <UPDATED_MANIFEST>.yaml
  6. Verify enforcement and residual usage

    • Confirm policies are active (policy‑engine specific; e.g., list Kyverno policies):
      kubectl get clusterpolicy,policy -A
    • Attempt to create a test pod with hostPort in a namespace where it should be denied and confirm it is rejected.
    • Re-run the evidence command to ensure only approved workloads (if any) still use hostPort:
      kubectl get pods -A -o jsonpath='{range .items[?(@.spec.containers[*].ports[*].hostPort)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{end}'
Using kubectl
# 1) List all namespaces to scope your review
# Run on: any machine with kubectl access
kubectl get namespaces -o name

Look for namespaces that contain user workloads (typically not kube-system, kube-public, kube-node-lease, or cloud-provider system namespaces) and review those first.

# 2) Find all Pods that currently use hostPort in all namespaces
# Run on: any machine with kubectl access
kubectl get pods -A -o jsonpath='{range .items[*]}{@.metadata.namespace}{" "}{@.metadata.name}{"\n"}{range @.spec.containers[*]}{range @.ports[*]}{..hostPort}{"\n"}{end}{end}{end}' | paste - - | grep -v ' $'

Output format:
<namespace> <pod-name> <hostPort-value>

Any line returned indicates a Pod with at least one container exposing a hostPort. You must manually decide if each such use is strictly necessary; widespread or unexplained hostPort use is a problem.

# 3) See full Pod specs using hostPort in a specific namespace
# Replace NAMESPACE with a namespace you identified above
kubectl get pods -n NAMESPACE -o yaml | grep -nA5 -B10 "hostPort:"

Review each occurrence of hostPort: and determine:

  • Is the hostPort needed (e.g., node-local DaemonSet, legacy integration)?
  • Could a Service/LoadBalancer/NodePort or Ingress replace it?

Multiple apps using the same hostPort on many nodes, or general-purpose workloads with hostPort but no clear justification, indicate a problem.

# 4) Identify PodSecurityPolicy or admission policies that already restrict hostPorts (if PSP is in use)
kubectl get podsecuritypolicies.policy -o yaml | grep -nA10 "hostPorts"

If hostPorts ranges are wide (e.g., 0-65535) or absent (no restriction at all), this suggests insufficient restriction and is a problem; narrow, explicit ranges only for known use cases are safer.

# 5) Inspect Pod Security admission labels (if using Pod Security Standards)
kubectl get ns --show-labels

Look for labels like pod-security.kubernetes.io/enforce=privileged or missing baseline/restricted labels on user namespaces. While Pod Security Standards do not directly block hostPort, very permissive or unset labels suggest that no higher-level guardrails exist, increasing risk when hostPort is used.

# 6) For a specific namespace, list all workload manifests to review for hostPort
kubectl get deploy,ds,sts,job,cronjob -n NAMESPACE -o yaml | grep -nA5 -B10 "hostPort:"

Any hostPort: in workload specs for general application Pods (web apps, APIs, batch jobs, etc.) is suspect. Only tightly controlled daemon-like workloads with clear operational justification should use hostPort.

Automation
#!/usr/bin/env bash
set -euo pipefail

# This script reports:
# 1) All Pods using hostPort
# 2) All workloads (Deployments/DaemonSets/StatefulSets/ReplicaSets/Jobs/CronJobs)
# that define hostPort in their Pod templates
# 3) Namespaces that lack a policy to restrict hostPorts (basic Gatekeeper/PSA hints)

TS="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
echo "=== HostPort usage report (${TS}) ==="
echo

###############################################################################
# 1) LIVE PODS USING hostPort
###############################################################################
echo "1) Pods currently running with hostPort set"
echo "------------------------------------------"

kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name, spec: .spec}
| .spec.containers + (.spec.initContainers // [])
| map({
ns: input_filename? // "N/A",
name: .name,
hostPort: (.ports // [] | map(select(.hostPort != null)) | .[])
})' 2>/dev/null >/dev/null && : || true

# simpler, robust jq:
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| ($pod.spec.containers + ($pod.spec.initContainers // []))
| map(
.ports // []
| map(select(.hostPort != null)
| {
namespace: $pod.metadata.namespace,
pod: $pod.metadata.name,
container: .name? // "N/A",
hostPort: .hostPort
}
)
)
| add // empty
' | sort -u || true

echo
echo "If any lines are printed above, those Pods are using hostPort and should be reviewed:"
echo "- Confirm business need for hostPort."
echo "- Prefer Service types (NodePort/LoadBalancer) or Ingress instead of hostPort."
echo

###############################################################################
# 2) WORKLOAD TEMPLATES DEFINING hostPort
###############################################################################
echo "2) Workloads whose Pod templates define hostPort"
echo "-----------------------------------------------"

# Helper function: scan a workload type
scan_workload() {
local kind="$1"
kubectl get "${kind}" --all-namespaces -o json 2>/dev/null \
| jq -r --arg KIND "${kind}" '
.items[]
| . as $w
| ($w.spec.template.spec.containers + ($w.spec.template.spec.initContainers // []))
| map(
.ports // []
| map(select(.hostPort != null)
| {
kind: $KIND,
namespace: $w.metadata.namespace,
name: $w.metadata.name,
container: .name? // "N/A",
hostPort: .hostPort
}
)
)
| add // empty
' || true
}

for k in deployments.apps daemonsets.apps statefulsets.apps replicasets.apps jobs.batch cronjobs.batch; do
scan_workload "$k"
done | sort -u

echo
echo "Any workloads listed above have hostPort in their Pod spec templates."
echo "These should be considered non-compliant unless there is a documented exception."
echo

###############################################################################
# 3) NAMESPACE-LEVEL POLICY HINTS
###############################################################################
echo "3) Namespace-level policies related to hostPort / Pod Security"
echo "-------------------------------------------------------------"

echo "3.a) Namespaces with PodSecurity admission labels (baseline/restricted)"
kubectl get ns --show-labels \
| sed 's/,/\n /g' \
| awk 'NR==1 || /pod-security.kubernetes.io/'

echo
echo "Namespaces without pod-security.kubernetes.io labels likely rely on default cluster policy."
echo "They may allow hostPorts unless restricted by another admission controller (e.g., Gatekeeper)."
echo

echo "3.b) Gatekeeper (if installed): Constraints that mention hostPort"
if kubectl get crd constraints.gatekeeper.sh >/dev/null 2>&1; then
kubectl get constraints.constraints.gatekeeper.sh --all-namespaces -o yaml 2>/dev/null \
| grep -i -n 'hostPort' || echo "No Gatekeeper constraints mentioning hostPort found."
else
echo "Gatekeeper constraints CRD not detected; skipping Gatekeeper policy scan."
fi

echo
echo "INTERPRETING POLICY OUTPUT:"
echo "- Namespaces that run user workloads and have Pods/workloads using hostPort"
echo " but no evident PodSecurity labels or hostPort-related constraints are likely risky."
echo "- Even with PodSecurity labels, you must verify that the policy level in use"
echo " actually disallows hostPort where it is not required."
echo
echo "Review the above data and decide, per namespace, which hostPort usages are justified."

How to run (any machine with kubectl access):

  1. Save as report-hostport-usage.sh.
  2. Make executable:
chmod +x report-hostport-usage.sh
  1. Run:
./report-hostport-usage.sh

Problem indicators in the output:

  • Any Pods or workloads listed in sections 1 or 2 in namespaces where hostPort is not strictly required.
  • Namespaces with such usage but:
    • No PodSecurity admission labels, and
    • No Gatekeeper (or similar) constraints that restrict spec.containers[].ports[].hostPort.

Additional Reading: