Skip to main content

Minimize Admission Of Windows HostProcess Containers

More Info:

Do not generally permit Windows containers to be run with the hostProcess flag set to true

Risk Level

Low

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Discover current usage of HostProcess in the cluster

    • Run on: any machine with kubectl access
    • Command (find all pods using hostProcess: true):
      kubectl get pods -A -o jsonpath='{range .items[?(@.spec.securityContext.windowsOptions.hostProcess==true)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{end}'
    • Command (find all containers using hostProcess: true at container level):
      kubectl get pods -A -o json | jq -r '
      .items[]
      | select(.spec.containers[]?.securityContext?.windowsOptions?.hostProcess == true
      or .spec.initContainers[]?.securityContext?.windowsOptions?.hostProcess == true)
      | .metadata.namespace + "\t" + .metadata.name
      ' | sort -u
  2. Identify namespaces with user workloads and HostProcess usage

    • Run on: any machine with kubectl access
    • Command (list namespaces that currently have any HostProcess pod/container):
      kubectl get pods -A -o json | jq -r '
      .items[]
      | select(
      .spec.securityContext?.windowsOptions?.hostProcess == true
      or (.spec.containers[]? | select(.securityContext?.windowsOptions?.hostProcess == true))
      or (.spec.initContainers[]? | select(.securityContext?.windowsOptions?.hostProcess == true))
      )
      | .metadata.namespace
      ' | sort -u
    • Separately, determine which of these namespaces are “user workload” namespaces (vs. system/addon namespaces) according to your cluster’s conventions.
  3. Review whether HostProcess is truly required in each affected user namespace

    • For each user namespace found in step 2, list workloads and their images:
      NAMESPACE=<namespace-name>
      kubectl get pods -n "$NAMESPACE" -o wide
      kubectl get pods -n "$NAMESPACE" -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
    • For each workload using HostProcess (from step 1), review its purpose (docs, owners, code) and decide:
      • Is HostProcess strictly needed (e.g., node management/diagnostics agents)?
      • Can it be redesigned to run without HostProcess (e.g., normal Windows container, sidecar pattern, or different privilege model)?
    • Document which specific deployments/DaemonSets, if any, are permitted to continue using HostProcess.
  4. Define or tighten admission policy per user namespace to restrict HostProcess

    • If you use Gatekeeper (OPA) or another admission controller, create or update a policy to deny new pods in target namespaces when any container or pod-level context has securityContext.windowsOptions.hostProcess: true, with explicit exceptions only for approved workloads from step 3. Example (Gatekeeper ConstraintTemplate/Constraint) must be implemented according to your existing policy framework; apply via manifest:
      kubectl apply -f <your-admission-policy-manifest>.yaml
    • If you have no admission policy framework, formally record that gap and plan adoption of a policy mechanism; without an admission controller there is no reliable automatic block on HostProcess.
  5. Remove or reconfigure unauthorized HostProcess workloads

    • For any workload in user namespaces where HostProcess is not justified:
      • Edit workload to remove HostProcess and redeploy:
        NAMESPACE=<namespace-name>
        WORKLOAD=<deployment-or-daemonset-name>

        # Example for a Deployment:
        kubectl -n "$NAMESPACE" edit deployment "$WORKLOAD"
        In the editor, remove or set to false any .spec.template.spec.securityContext.windowsOptions.hostProcess, and any container-level .securityContext.windowsOptions.hostProcess. Save and exit to trigger rollout.
      • If the workload’s function is no longer needed, delete it:
        kubectl -n "$NAMESPACE" delete deployment <name>
        # or
        kubectl -n "$NAMESPACE" delete daemonset <name>
  6. Verify that HostProcess usage is minimized and policy is effective

    • Run on: any machine with kubectl access
    • Re-run the evidence commands to confirm no unauthorized HostProcess pods remain:
      kubectl get pods -A -o jsonpath='{range .items[?(@.spec.securityContext.windowsOptions.hostProcess==true)]}{.metadata.namespace}{"\t"}{.metadata.name}{"\n"}{end}'
      kubectl get pods -A -o json | jq -r '
      .items[]
      | select(.spec.containers[]?.securityContext?.windowsOptions?.hostProcess == true
      or .spec.initContainers[]?.securityContext?.windowsOptions?.hostProcess == true)
      | .metadata.namespace + "\t" + .metadata.name
      ' | sort -u
    • Attempt to create a simple test pod in a protected user namespace with hostProcess: true and confirm that the admission policy rejects it (or, if you have no admission controller, explicitly record that no technical enforcement exists and rely on process controls).
Using kubectl
# 1) List all namespaces that might host user workloads
# (run on any machine with kubectl access)
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| grep -Ev '^(kube-system|kube-public|kube-node-lease|default)$'

Output to review:
A list of namespaces where you should evaluate whether Windows HostProcess containers are appropriate. Any namespace that runs multi-tenant or untrusted workloads should be treated as high-risk if HostProcess is allowed.


# 2) Find existing pods using Windows HostProcess in all namespaces
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No pods with hostProcess=true found"

Problem indication:
Any line printed (not including the "No pods..." message) shows a pod with hostProcess=true. For each such pod, you must decide whether it is strictly necessary and whether it’s placed only in namespaces where this level of privilege is acceptable.


# 3) Inspect deployments/statefulsets/daemonsets that may create HostProcess pods

# Deployments
kubectl get deploy -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No deployments with hostProcess=true found"

# StatefulSets
kubectl get statefulset -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No statefulsets with hostProcess=true found"

# DaemonSets
kubectl get daemonset -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No daemonsets with hostProcess=true found"

Problem indication:
Any workload object listed with hostProcess=true will continuously create HostProcess pods. You must review whether each such workload is necessary and whether its namespace should allow HostProcess at all.


# 4) Check PodSecurity or Pod Security Admission labels on each namespace
kubectl get ns --show-labels

Problem indication:
Look for labels like pod-security.kubernetes.io/enforce, pod-security.kubernetes.io/audit, or pod-security.kubernetes.io/warn.
If namespaces running untrusted or general user workloads have no PodSecurity labels, or are set to a profile that does not restrict HostProcess usage, this is a risk. A human must decide if stricter profiles should be applied.


# 5) Discover any Gatekeeper/PSP-like policies that may already restrict HostProcess

# Gatekeeper (if installed)
kubectl get constrainttemplates.constraints.gatekeeper.sh -A 2>/dev/null || echo "No Gatekeeper constraint templates found (or Gatekeeper not installed)"

kubectl get constraints -A 2>/dev/null || echo "No Gatekeeper constraints found"

# Legacy PodSecurityPolicies (if still present)
kubectl get psp 2>/dev/null || echo "No PodSecurityPolicies found (or API disabled)"

Problem indication:
If no constraints or PSPs are found that mention windowsOptions or hostProcess, then there may be no central policy preventing arbitrary use of Windows HostProcess containers. A human must determine whether additional policy is required.


# 6) Detailed review of a specific namespace (replace with the namespace under review)
kubectl get pods -n NAMESPACE -o yaml | grep -nE 'windowsOptions:|hostProcess:' -n

Problem indication:
Any occurrence of hostProcess: true in a namespace that is intended for regular or multi-tenant workloads is a concern. You must decide whether to redesign these workloads or move them to tightly controlled namespaces.


Verification after changes (policy or workload updates done manually):

# Re-run pod/workload scans to confirm no unexpected HostProcess usage
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No pods with hostProcess=true found"

kubectl get deploy -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No deployments with hostProcess=true found"

kubectl get statefulset -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No statefulsets with hostProcess=true found"

kubectl get daemonset -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -w "true" || echo "No daemonsets with hostProcess=true found"

If the only remaining hostProcess=true usages are in tightly controlled, explicitly approved namespaces, and admission policies for user-workload namespaces are in place (as manually confirmed), the finding is addressed.

Automation
#!/usr/bin/env bash
# Report Windows HostProcess usage across all namespaces
# Run on: any machine with kubectl access and current context set to the target cluster

set -euo pipefail

echo "Scanning Pods for windowsOptions.hostProcess = true ..."
echo "------------------------------------------------------------------"

kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| (
($pod.spec.containers // []) +
($pod.spec.initContainers // []) +
($pod.spec.ephemeralContainers // [])
)[]
| select(
.securityContext.windowsOptions.hostProcess == true
)
| [
$pod.metadata.namespace,
$pod.metadata.name,
.name,
($pod.spec.nodeName // "N/A"),
($pod.spec.securityContext.windowsOptions.os // "N/A"),
"hostProcess=true"
]
| @tsv' | sort | column -t \
|| echo "No Pods with windowsOptions.hostProcess=true found or error running query."

echo
echo "Scanning PodTemplates (e.g., Deployments, DaemonSets, StatefulSets, Jobs, CronJobs) for hostProcess=true ..."
echo "------------------------------------------------------------------"

kubectl get deploy,ds,sts,job,cronjob --all-namespaces -o json \
| jq -r '
.items[]
| . as $obj
| .spec.template as $tpl
| (
($tpl.spec.containers // []) +
($tpl.spec.initContainers // []) +
($tpl.spec.ephemeralContainers // [])
)[]
| select(
.securityContext.windowsOptions.hostProcess == true
)
| [
$obj.metadata.namespace,
$obj.kind,
$obj.metadata.name,
.name,
($tpl.spec.nodeName // "N/A"),
($tpl.spec.securityContext.windowsOptions.os // "N/A"),
"hostProcess=true"
]
| @tsv' | sort | column -t \
|| echo "No PodTemplates with windowsOptions.hostProcess=true found or error running query."

echo
echo "Summary of namespaces with hostProcess=true workloads ..."
echo "------------------------------------------------------------------"

kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| (
($pod.spec.containers // []) +
($pod.spec.initContainers // []) +
($pod.spec.ephemeralContainers // [])
)[]
| select(
.securityContext.windowsOptions.hostProcess == true
)
| $pod.metadata.namespace
' | sort -u || true

How to interpret the output

  • Any line in the first two sections indicates a workload that is running or configured with securityContext.windowsOptions.hostProcess=true.
    • Columns are: NAMESPACE POD/WORKLOAD_NAME CONTAINER_NAME NODE OS hostProcess=true.
  • The final section lists namespaces that currently admit HostProcess workloads; these namespaces need manual review and, if not strictly required, admission policies to restrict windowsOptions.hostProcess=true as per the benchmark guidance.

Additional Reading: