Minimize Admission Containers Wishing Host IPC Namespace
More Info:
Do not generally permit containers to be run with the hostIPC flag set to true.
Risk Level
Critical
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify pods currently using
hostIPC(any machine with kubectl access):kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | \while read -r pod_name pod_namespace; dopod_hostipc=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostIPC}' 2>/dev/null)if [ "${pod_hostipc}" = "true" ]; thenecho "POD: ${pod_name} NAMESPACE: ${pod_namespace} hostIPC: true"fidone -
For each affected namespace, review whether any workload must legitimately use
hostIPC(design/ops decision):- List pods and their controllers:
kubectl get pods -n <NAMESPACE> -o widekubectl get deploy,sts,ds,job,cronjob -n <NAMESPACE>
- With application owners, decide whether
hostIPC: trueis strictly required; if not, plan to remove it and block future use.
- List pods and their controllers:
-
Remove
hostIPCfrom existing workload specs (any machine with kubectl access):- For a Deployment (repeat for other controllers as needed):
Editkubectl -n <NAMESPACE> get deploy <DEPLOYMENT_NAME> -o yaml > /tmp/deploy-no-hostipc.yaml
/tmp/deploy-no-hostipc.yamland remove any line like:from underhostIPC: truespec.template.spec.- Apply the change:
kubectl apply -f /tmp/deploy-no-hostipc.yaml
- Apply the change:
- Repeat similarly for StatefulSets, DaemonSets, Jobs, and CronJobs in that namespace.
- For a Deployment (repeat for other controllers as needed):
-
Create or update a PodSecurityPolicy (if still in use in your cluster) or Pod Security admission configuration to disallow
hostIPCin user namespaces (any machine with kubectl access):Example PodSecurityPolicy (if PSP enabled):
cat >/tmp/psp-no-hostipc.yaml <<'EOF'apiVersion: policy/v1beta1kind: PodSecurityPolicymetadata:name: disallow-hostipcspec:hostIPC: falseprivileged: falseseLinux:rule: RunAsAnyrunAsUser:rule: RunAsAnyfsGroup:rule: RunAsAnysupplementalGroups:rule: RunAsAnyvolumes:- '*'EOFkubectl apply -f /tmp/psp-no-hostipc.yamlThen bind it to service accounts in user namespaces:
cat >/tmp/psp-no-hostipc-rb.yaml <<'EOF'apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:name: use-psp-disallow-hostipcrules:- apiGroups: ["policy"]resources: ["podsecuritypolicies"]verbs: ["use"]resourceNames: ["disallow-hostipc"]---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:name: use-psp-disallow-hostipcroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: use-psp-disallow-hostipcsubjects:- kind: Groupname: system:serviceaccountsapiGroup: rbac.authorization.k8s.ioEOFkubectl apply -f /tmp/psp-no-hostipc-rb.yamlIf you use the built-in Pod Security admission instead of PSP, ensure user namespaces are labeled with a policy level that forbids
hostIPC(e.g.restricted), after reviewing impact:kubectl label namespace <NAMESPACE> pod-security.kubernetes.io/enforce=restricted --overwrite -
Test admission control behavior in a non-production namespace (any machine with kubectl access):
kubectl create namespace hostipc-testkubectl label namespace hostipc-test pod-security.kubernetes.io/enforce=restricted --overwritecat >/tmp/hostipc-test-pod.yaml <<'EOF'apiVersion: v1kind: Podmetadata:name: hostipc-test-podnamespace: hostipc-testspec:hostIPC: truecontainers:- name: pauseimage: registry.k8s.io/pause:3.9EOFkubectl apply -f /tmp/hostipc-test-pod.yamlConfirm that admission is rejected (pod is not created and an error is returned). After testing, you may delete the test namespace:
kubectl delete namespace hostipc-test -
Verification (any machine with kubectl access):
kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | \while read -r pod_name pod_namespace; dopod_hostipc=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostIPC}' 2>/dev/null)if [ -z "${pod_hostipc}" ]; thenpod_hostipc="false"echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostipc: ${pod_hostipc} is_compliant: true"elseecho "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostipc: ${pod_hostipc} is_compliant: false"fidoneReview output and ensure no pods report
is_pod_hostipc: true.
Using kubectl
On any machine with kubectl access:
- Identify namespaces with user workloads (example list; adjust to your environment):
kubectl get ns
- Create a restrictive PodSecurityPolicy (if PSP is enabled) or a validating policy via a policy engine (e.g., Kyverno, Gatekeeper). Below are example manifests you can adapt; choose the mechanism actually available in your cluster.
Example: Kyverno policy to block hostIPC pods
Save as deny-hostipc-pods.yaml:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-hostipc
spec:
validationFailureAction: enforce
background: true
rules:
- name: check-hostipc
match:
any:
- resources:
kinds:
- Pod
namespaces:
- "default"
- "prod"
- "staging"
validate:
message: "Using hostIPC is not allowed in this namespace."
pattern:
spec:
=(hostIPC): "false"
Apply:
kubectl apply -f deny-hostipc-pods.yaml
Edit the namespaces list in the manifest to cover each namespace that hosts user workloads.
Example: Gatekeeper (OPA) ConstraintTemplate + Constraint
Save as hostipc-template.yaml:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sdenydisallowedhostipc
spec:
crd:
spec:
names:
kind: K8sDenyDisallowedHostIPC
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdenydisallowedhostipc
violation[{"msg": msg}] {
input.review.kind.kind == "Pod"
hostipc := input.review.object.spec.hostIPC
hostipc == true
msg := "Using hostIPC is not allowed in this namespace."
}
Apply:
kubectl apply -f hostipc-template.yaml
Then create a constraint, e.g. hostipc-constraint.yaml:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyDisallowedHostIPC
metadata:
name: disallow-hostipc
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "default"
- "prod"
- "staging"
Apply:
kubectl apply -f hostipc-constraint.yaml
Update the namespaces list as needed.
Example: PodSecurityPolicy (only if PSP is enabled)
Save as psp-no-hostipc.yaml:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp-no-hostipc
spec:
privileged: false
hostIPC: false
seLinux:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- '*'
Apply:
kubectl apply -f psp-no-hostipc.yaml
Then bind it per namespace (example for prod):
# file: psp-no-hostipc-rb-prod.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: use-psp-no-hostipc
namespace: prod
rules:
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames: ["psp-no-hostipc"]
verbs: ["use"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: use-psp-no-hostipc
namespace: prod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: use-psp-no-hostipc
subjects:
- kind: Group
name: system:serviceaccounts:prod
apiGroup: rbac.authorization.k8s.io
Apply:
kubectl apply -f psp-no-hostipc-rb-prod.yaml
Repeat the Role/RoleBinding per namespace that hosts user workloads.
- Verification (re-run the provided audit):
kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | while read -r pod_name pod_namespace
do
pod_hostipc=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostIPC}' 2>/dev/null)
if [ -z "${pod_hostipc}" ]; then
pod_hostipc="false"
echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostipc: ${pod_hostipc} is_compliant: true"
else
echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostipc: ${pod_hostipc} is_compliant: false"
fi
done
Confirm no new pods with is_pod_hostipc: true can be created in the protected namespaces.
Automation
#!/usr/bin/env bash
# Purpose: Minimize admission of pods with hostIPC=true by applying a restrictive
# PodSecurityPolicy/PodSecurityStandard-style policy (via PodSecurity admission labels)
# to all user namespaces.
#
# Scope: Run on any machine with kubectl access and appropriate permissions.
# Idempotent: Safe to re-run; it only adds/updates labels and does not delete objects.
#
# NOTE:
# - This benchmark control is MANUAL: you must review workloads that truly need hostIPC.
# - This script focuses on *preventing new* hostIPC pods in user namespaces.
# - It does NOT modify or evict existing pods that already use hostIPC=true.
set -euo pipefail
# ------------- Configuration (EDIT IF NEEDED) ----------------
# Regex to identify system namespaces which should be excluded from enforcement
# (kube-system and similar). You can extend this list if needed.
SYSTEM_NS_REGEX='^(kube-system|kube-public|kube-node-lease|default)$'
# Desired Pod Security admission levels for user namespaces.
# 'restricted' denies hostIPC and other privileged features.
POD_SECURITY_ENFORCE_LEVEL="restricted"
POD_SECURITY_AUDIT_LEVEL="restricted"
POD_SECURITY_WARN_LEVEL="restricted"
# --------------------------------------------------------------
echo "[INFO] Verifying kubectl connectivity..."
kubectl version --short >/dev/null
echo "[INFO] Discovering namespaces..."
all_namespaces=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
user_namespaces=()
while IFS= read -r ns; do
if [[ ! "$ns" =~ $SYSTEM_NS_REGEX ]]; then
user_namespaces+=("$ns")
fi
done <<< "$all_namespaces"
if [ ${#user_namespaces[@]} -eq 0 ]; then
echo "[INFO] No user namespaces found (only system namespaces match). Nothing to do."
else
echo "[INFO] User namespaces to process:"
printf ' - %s\n' "${user_namespaces[@]}"
fi
# ------------- Apply restrictive PodSecurity labels -------------
for ns in "${user_namespaces[@]}"; do
echo "[INFO] Applying PodSecurity labels to namespace: $ns"
# Idempotent label application (add/update as needed)
kubectl label namespace "$ns" \
"pod-security.kubernetes.io/enforce=$POD_SECURITY_ENFORCE_LEVEL" \
"pod-security.kubernetes.io/audit=$POD_SECURITY_AUDIT_LEVEL" \
"pod-security.kubernetes.io/warn=$POD_SECURITY_WARN_LEVEL" \
--overwrite
done
# ------------- Manual review guidance for existing hostIPC pods -------------
echo "[INFO] Listing existing pods with hostIPC=true (for manual review)..."
kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | \
while read -r pod_name pod_namespace; do
pod_hostipc=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostIPC}' 2>/dev/null || true)
if [ -n "${pod_hostipc}" ] && [ "${pod_hostipc}" = "true" ]; then
echo " [WARNING] Existing hostIPC pod: ${pod_namespace}/${pod_name}"
fi
done || true
cat <<'EOF'
[NOTE] The control is MANUAL:
- Review each WARNING line above to determine if hostIPC=true is strictly necessary.
- For each workload where hostIPC is not required, update its Deployment/PodSpec to remove `hostIPC: true`.
- For workloads that truly require hostIPC, consider:
* Running them only in tightly controlled namespaces.
* Applying more targeted admission controls (e.g., admission webhook, Gatekeeper policies).
EOF
# ------------- Verification (adapted from audit) ----------------
echo "[INFO] Re-running audit to verify current state of hostIPC usage..."
kubectl get pods --all-namespaces -o custom-columns=POD_NAME:.metadata.name,POD_NAMESPACE:.metadata.namespace --no-headers | \
while read -r pod_name pod_namespace; do
pod_hostipc=$(kubectl get pod "${pod_name}" --namespace "${pod_namespace}" -o jsonpath='{.spec.hostIPC}' 2>/dev/null || true)
if [ -z "${pod_hostipc}" ]; then
pod_hostipc="false"
echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostipc: ${pod_hostipc} is_compliant: true"
else
echo "***pod_name: ${pod_name} pod_namespace: ${pod_namespace} is_pod_hostipc: ${pod_hostipc} is_compliant: false"
fi
done