Minimize The Admission Of Windows HostProcess Containers
More Info:
Windows HostProcess containers run with host-level privileges on the node. Restrict their admission in workload namespaces.
Risk Level
High
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify Windows HostProcess workloads in user namespaces
- Run on: any machine with kubectl access
- Command (lists pods that explicitly request HostProcess):
kubectl get pods --all-namespaces -o json \| jq -r '.items[]| select(.spec.securityContext.windowsOptions.hostProcess == trueor ([.spec.containers[], (.spec.initContainers // [])[]?| select(.securityContext.windowsOptions.hostProcess == true)] | length) > 0)| [.metadata.namespace, .metadata.name] | @tsv'
- Repeat, but exclude known infrastructure namespaces (adjust as appropriate for your cluster):
kubectl get pods --all-namespaces -o json \| jq -r '.items[]| select(.metadata.namespace as $ns| ($ns | IN("kube-system","kube-public","kube-node-lease","kube-*","azure-*","aws-*","gke-*") | not))| select(.spec.securityContext.windowsOptions.hostProcess == trueor ([.spec.containers[], (.spec.initContainers // [])[]?| select(.securityContext.windowsOptions.hostProcess == true)] | length) > 0)| [.metadata.namespace, .metadata.name] | @tsv'
-
Decide where HostProcess containers are allowed (policy design)
- For each user namespace, decide one of:
- No HostProcess allowed (typical for most workloads).
- HostProcess allowed only for specific, justified workloads (e.g., node maintenance agents).
- Document for each namespace whether HostProcess is: forbidden, tightly controlled, or not yet decided.
- For each user namespace, decide one of:
-
Review and, if needed, create/adjust admission controls (Pod Security or other)
- If using built-in Pod Security Admission labels, for each user namespace that should forbid HostProcess, label it with at least
baselineorrestricted(both disallow HostProcess):# Example: enforce restricted profile, which disallows Windows HostProcesskubectl label namespace <USER_NAMESPACE> \pod-security.kubernetes.io/enforce=restricted \pod-security.kubernetes.io/enforce-version=latest \--overwrite - If you use another admission controller (e.g., Gatekeeper, Kyverno), review existing policies to ensure they deny pods with
.securityContext.windowsOptions.hostProcess: truein any namespace that should not allow them. Use:kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io -o yamlkubectl get constrainttemplates,constraints,clusterpolicies,policies -A -o yaml 2>/dev/null | less - Where HostProcess must be allowed, design exception rules (e.g., labels/annotations on specific namespaces or service accounts) and ensure policies only allow HostProcess under those constrained conditions.
- If using built-in Pod Security Admission labels, for each user namespace that should forbid HostProcess, label it with at least
-
Implement or tighten deny policies for HostProcess in user namespaces
- Example Kyverno ClusterPolicy to deny all HostProcess containers except in explicitly allowed namespaces (
windows-hostprocess-allowed=true):apiVersion: kyverno.io/v1kind: ClusterPolicymetadata:name: deny-windows-hostprocessspec:validationFailureAction: enforcebackground: truerules:- name: deny-hostprocessmatch:any:- resources:kinds:- Podexclude:any:- resources:namespaces:- kube-system- resources:namespaceSelector:matchLabels:windows-hostprocess-allowed: "true"validate:message: "Windows HostProcess containers are not allowed in this namespace."pattern:spec:securityContext:windowsOptions:hostProcess: "false"containers:- (name): "*"securityContext:windowsOptions:hostProcess: "false"=(initContainers):- (name): "*"securityContext:windowsOptions:hostProcess: "false" - Apply (adjust as needed for your own policy engine):
kubectl apply -f deny-windows-hostprocess.yaml
- Example Kyverno ClusterPolicy to deny all HostProcess containers except in explicitly allowed namespaces (
-
Handle existing HostProcess pods in disallowed namespaces
- For each pod from step 1 that is in a namespace now marked to forbid HostProcess:
- Confirm with the owner whether the HostProcess capability is truly required.
- If not required: update the pod spec / owning controller (Deployment, DaemonSet, Job, etc.) to remove
.securityContext.windowsOptions.hostProcess: true, then redeploy. - If required: either
- move the workload to a dedicated namespace explicitly marked to allow HostProcess (e.g., label
windows-hostprocess-allowed=true), and keep strict controls there, or - adjust your policy design to formally permit it with documented justification.
- move the workload to a dedicated namespace explicitly marked to allow HostProcess (e.g., label
- For each pod from step 1 that is in a namespace now marked to forbid HostProcess:
-
Verify that HostProcess admission is now minimized
- Re-run the detection command to confirm there are no HostProcess pods in namespaces where they should be forbidden:
kubectl get pods --all-namespaces -o json \| jq -r '.items[]| select(.spec.securityContext.windowsOptions.hostProcess == trueor ([.spec.containers[], (.spec.initContainers // [])[]?| select(.securityContext.windowsOptions.hostProcess == true)] | length) > 0)| [.metadata.namespace, .metadata.name] | @tsv'
- Independently test admission by attempting to create a sample HostProcess pod in a user namespace that should reject it and confirm it fails with a policy error:
Confirm the admission controller rejects this pod creation.cat <<'EOF' | kubectl apply -f -apiVersion: v1kind: Podmetadata:name: test-hostprocess-denynamespace: <USER_NAMESPACE_THAT_SHOULD_DENY>spec:os:name: windowssecurityContext:windowsOptions:hostProcess: truecontainers:- name: testimage: mcr.microsoft.com/windows/nanoserver:ltsc2022command: ["cmd", "/c", "ping -t 127.0.0.1"]securityContext:windowsOptions:hostProcess: trueEOF
- Re-run the detection command to confirm there are no HostProcess pods in namespaces where they should be forbidden:
Using kubectl
# 1) List all namespaces that may host user workloads
# Run on: any machine with kubectl access
kubectl get ns
# 2) For each user-workload namespace, list policies that might control HostProcess:
# (ValidatingWebhookConfiguration, MutatingWebhookConfiguration, and constraints)
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations,validatingpolicies,validatingadmissionpolicies,clusterrolebindings,rolebindings -A
# 3) Identify current HostProcess usage in all namespaces
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -iw "true" || echo "No pods with windowsOptions.hostProcess=true found"
# 4) Also check container-level windowsOptions on existing pods
kubectl get pods -A -o json \
| jq -r '
.items[]
| . as $pod
| ($pod.spec.containers[]?, $pod.spec.initContainers[]?)
| select(.securityContext.windowsOptions.hostProcess == true)
| [$pod.metadata.namespace, $pod.metadata.name, .name, "true"]
| @tsv
'
# 5) Inspect a specific namespace for HostProcess-true pods (replace NAMESPACE)
kubectl get pods -n kube-system -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -iw "true" || echo "No HostProcess pods in kube-system"
# 6) Look for policies that explicitly mention windowsOptions/hostProcess
kubectl get validatingwebhookconfigurations -o yaml | grep -nE 'windowsOptions|hostProcess' || echo "No hostProcess-related validating webhooks found"
kubectl get mutatingwebhookconfigurations -o yaml | grep -nE 'windowsOptions|hostProcess' || echo "No hostProcess-related mutating webhooks found"
# 7) If using ValidatingAdmissionPolicy (v1), inspect for hostProcess conditions
kubectl get validatingadmissionpolicies -o yaml | grep -nE 'windowsOptions|hostProcess' || echo "No hostProcess-related ValidatingAdmissionPolicies found"
Interpretation (what indicates a problem):
-
Step 3 / 4 / 5 outputs:
- Any line where the last column is
truemeans there is at least one Windows HostProcess container currently running in that namespace. That is not automatically wrong, but such pods should be reviewed and justified; user-workload namespaces should generally not contain HostProcess containers unless there is a documented, approved need.
- Any line where the last column is
-
Step 2 / 6 / 7 outputs:
- If there are no Validating/Mutating webhooks or ValidatingAdmissionPolicies that reference
windowsOptionsorhostProcess, then there is likely no explicit admission control restricting Windows HostProcess containers. - In user-workload namespaces, “no hostProcess-related policies found” combined with evidence of HostProcess-true pods from steps 3–5 suggests a policy gap that needs human review and a possible policy design.
- If there are no Validating/Mutating webhooks or ValidatingAdmissionPolicies that reference
Verification after any policy changes:
# Re-check for admitted HostProcess containers
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.securityContext.windowsOptions.hostProcess}{"\n"}{end}' \
| grep -iw "true" || echo "No pods with windowsOptions.hostProcess=true found"
# Confirm that at least one admission policy references hostProcess
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations,validatingadmissionpolicies -A -o yaml \
| grep -nE 'windowsOptions|hostProcess' || echo "No hostProcess-related admission controls detected"
These commands only surface state; a human must decide which namespaces may legitimately allow Windows HostProcess containers and what policy to apply.
Automation
#!/usr/bin/env bash
# Purpose:
# Report Windows HostProcess containers across all namespaces for review.
# Runs with: any machine with kubectl access and cluster-wide read permissions.
set -euo pipefail
echo "Scanning for Windows HostProcess containers in all namespaces..."
echo
# 1) List all pods that declare any HostProcess container
kubectl get pods -A -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
pod: .metadata.name,
node: (.spec.nodeName // "UNSCHEDULED"),
os: (.spec.nodeSelector."kubernetes.io/os"
// .spec.nodeSelector."kubernetes.io/arch"
// "unknown"),
containers: (
[
(.spec.containers[]? | {name, hp: (.securityContext.windowsOptions.hostProcess // false), type:"container"}),
(.spec.initContainers[]? | {name, hp: (.securityContext.windowsOptions.hostProcess // false), type:"initContainer"}),
(.spec.ephemeralContainers[]? | {name, hp: (.securityContext.windowsOptions.hostProcess // false), type:"ephemeralContainer"})
]
)
}
| select([.containers[].hp] | any)
| [
.ns,
.pod,
.node,
.os,
(
.containers
| map(select(.hp == true) | "\(.type):\(.name)")
| join(",")
)
]
| @tsv
' 2>/dev/null \
| sort -k1,1 -k2,2 \
| awk 'BEGIN {
FS="\t";
printf "%-30s %-40s %-35s %-12s %s\n", "NAMESPACE", "POD", "NODE", "OS", "HOSTPROCESS_CONTAINERS";
print "---------------------------------------------------------------------------------------------------------------------------------------";
}
{
printf "%-30s %-40s %-35s %-12s %s\n", $1, $2, $3, $4, $5;
}'
echo
echo "Detail per HostProcess pod (namespace/pod -> container -> spec fragment):"
echo "---------------------------------------------------------------------------"
# 2) Show focused spec fragments for each HostProcess container for deeper review
kubectl get pods -A -o json \
| jq -r '
.items[]
| select(
[
(.spec.containers[]?.securityContext.windowsOptions.hostProcess // false),
(.spec.initContainers[]?.securityContext.windowsOptions.hostProcess // false),
(.spec.ephemeralContainers[]?.securityContext.windowsOptions.hostProcess // false)
] | any
)
| "---- " + .metadata.namespace + "/" + .metadata.name,
(
[
(.spec.containers[]? | select(.securityContext.windowsOptions.hostProcess == true)),
(.spec.initContainers[]? | select(.securityContext.windowsOptions.hostProcess == true)),
(.spec.ephemeralContainers[]? | select(.securityContext.windowsOptions.hostProcess == true))
]
| .[]
| "container: " + .name,
"spec:",
( { securityContext: { windowsOptions: .securityContext.windowsOptions } } | tojson ),
""
)
'
cat <<'EOF'
Interpretation / what indicates a problem
-----------------------------------------
- Any row in the summary table above indicates a pod that includes at least one
container with securityContext.windowsOptions.hostProcess = true.
- These pods should exist only where there is an explicit, justified operational
requirement (for example, privileged Windows node management DaemonSets).
- Findings that typically require action:
* HostProcess containers running in general-purpose application namespaces.
* HostProcess containers that were not explicitly approved by the security team.
* Namespaces where you expected policies (e.g., Pod Security Admission,
Gatekeeper, Kyverno) to deny HostProcess but the table still shows pods.
Use this report to:
- Identify namespaces that need admission controls to restrict HostProcess usage.
- Review each listed pod and decide whether to:
* Keep it (documented exception) and enforce tight controls; or
* Replace it with a non-HostProcess design and add/strengthen policies that
block future HostProcess containers in that namespace.
There is no safe, deterministic script to auto-fix these workloads: changes
must be made per-namespace and per-application, based on operational needs.
EOF