Skip to main content

Minimize The Admission Of Containers Sharing The Host IPC

More Info:​

Containers sharing the host IPC namespace can access inter-process communication resources of the node. Restrict admission of hostIPC containers via namespace policies.

Risk Level​

High

Address​

Security

Compliance Standards​

  • CIS EKS

Triage and Remediation​

Remediation​

Manual Steps
  1. Identify pods using hostIPC (informational).
    Run on any machine with kubectl access:

    kubectl get pods --all-namespaces -o json \
    | jq -r '.items[] | select(.spec.hostIPC == true) | "\(.metadata.namespace) \(.metadata.name)"'
  2. Review and plan to change offending workloads.
    For each listed pod, identify the owning workload (Deployment/StatefulSet/Job, etc.):

    # Example for one namespace
    kubectl get pods -n NAMESPACE PODNAME -o json \
    | jq -r '.metadata.ownerReferences[]? | "\(.kind)/\(.name)"'

    Decide whether hostIPC is truly required. If absolutely required, document the exception and plan a Pod Security (or PSP/replacement) policy that narrowly permits it only where needed.

  3. Remove hostIPC: true from workload manifests.
    For each offending workload, edit the manifest and delete the hostIPC: true line under spec.template.spec (or under spec for naked Pods). Example using kubectl edit (on any machine with kubectl access):

    # Deployment example
    kubectl edit deployment -n NAMESPACE DEPLOYMENT_NAME

    In the editor, remove:

    spec:
    template:
    spec:
    hostIPC: true

    Save and exit. Repeat for StatefulSets, Jobs, DaemonSets, and any standalone Pods.

  4. Apply restrictive Pod Security (or equivalent) policy at the namespace level.
    For Kubernetes 1.25+ using Pod Security admission, label each namespace with at least restricted (which forbids hostIPC: true by default):

    kubectl label namespace NAMESPACE \
    pod-security.kubernetes.io/enforce=restricted \
    pod-security.kubernetes.io/enforce-version=latest --overwrite

    Repeat for every namespace that hosts user workloads.

  5. Recreate or roll pods so changes take effect.
    For controller-managed workloads (Deployments/StatefulSets/DaemonSets), trigger a rollout:

    kubectl rollout restart deployment -n NAMESPACE DEPLOYMENT_NAME
    kubectl rollout restart statefulset -n NAMESPACE STATEFULSET_NAME
    kubectl rollout restart daemonset -n NAMESPACE DAEMONSET_NAME

    For any remaining naked Pods that specified hostIPC: true, delete and recreate them from the updated manifests:

    kubectl delete pod -n NAMESPACE PODNAME
    kubectl apply -f /absolute/path/to/updated-pod-manifest.yaml
  6. Verify no pods use hostIPC.
    Run on any machine with kubectl access:

    kubectl get pods --all-namespaces -o json \
    | jq -r 'if any(.items[]?; .spec.hostIPC == true) then "HOSTIPC_FOUND" else "NO_HOSTIPC" end'

    Ensure the output is:

    NO_HOSTIPC
Using kubectl

On any machine with kubectl access:

  1. Create a restrictive PodSecurity admission label (for clusters using Pod Security Admission)
kubectl label namespace default pod-security.kubernetes.io/enforce=restricted --overwrite
kubectl label namespace default pod-security.kubernetes.io/enforce-version=latest --overwrite

Apply similar labels to every namespace that runs user workloads, replacing default:

kubectl get ns
# For each relevant namespace, e.g.:
kubectl label namespace my-apps pod-security.kubernetes.io/enforce=restricted --overwrite
kubectl label namespace my-apps pod-security.kubernetes.io/enforce-version=latest --overwrite
  1. (Alternative/Additional) Apply a PodSecurityPolicy-style restriction via Gatekeeper/PSP replacement
    If you use Gatekeeper or a similar admission controller, apply a policy that disallows hostIPC: true in pods. Example Gatekeeper ConstraintTemplate and Constraint (save as deny-hostipc.yaml and apply):
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sdenyhostipc
spec:
crd:
spec:
names:
kind: K8sDenyHostIPC
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdenyhostipc

violation[{"msg": msg}] {
input.review.kind.kind == "Pod"
input.review.object.spec.hostIPC == true
msg := "Pods must not set spec.hostIPC=true"
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyHostIPC
metadata:
name: deny-hostipc
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "*"

Apply:

kubectl apply -f deny-hostipc.yaml
  1. Verification (any machine with kubectl access)
kubectl get pods --all-namespaces -o json | jq -r 'if any(.items[]?; .spec.hostIPC == true) then "HOSTIPC_FOUND" else "NO_HOSTIPC" end'
Automation
#!/usr/bin/env bash
set -euo pipefail

# This script:
# - Creates a PodSecurity "restricted" level default policy in every user namespace
# - Ensures hostIPC is disallowed for new pods (and pod templates) in those namespaces
# - Verifies no pods are currently using hostIPC
#
# Run from: any machine with kubectl access and a current-context pointing at the cluster.

# -------------------------
# Configurable allowlist
# -------------------------
# Namespaces to skip (typically system/control-plane namespaces).
SKIP_NAMESPACES=(
"kube-system"
"kube-public"
"kube-node-lease"
"default" # remove from this list if you run user workloads here
"local-path-storage"
"kube-monitoring"
"calico-system"
"tigera-operator"
"istio-system"
"cert-manager"
)

# Convert skip list to a regex for grep -wF -x
skip_ns_regex="$(printf '%s\n' "${SKIP_NAMESPACES[@]}" | sed 's/[.[\*^$]/\\&/g' | paste -sd'|' -)"

echo "Discovering namespaces..."
all_ns="$(kubectl get ns -o jsonpath='{.items[*].metadata.name}')"

user_ns=()
for ns in $all_ns; do
if [[ -n "$skip_ns_regex" ]] && [[ "$ns" =~ ^($skip_ns_regex)$ ]]; then
echo "Skipping namespace (allowlisted): $ns"
continue
fi
user_ns+=("$ns")
done

if [[ ${#user_ns[@]} -eq 0 ]]; then
echo "No user namespaces discovered after applying skip list."
fi

# -------------------------
# Apply Pod Security Standards labels
# -------------------------
# This uses the built-in PodSecurity admission (PSA) labels to enforce "restricted",
# which forbids hostIPC for new pods in these namespaces.
#
# If you are already using PodSecurity labels, this will idempotently set them to
# enforce=restricted, audit=restricted, warn=restricted.

for ns in "${user_ns[@]}"; do
echo "Configuring PodSecurity 'restricted' policy in namespace: $ns"

# Set or update labels idempotently
kubectl label namespace "$ns" \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/audit-version=latest \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/warn-version=latest \
--overwrite
done

# -------------------------
# Optional: Add an explicit validating admission policy for hostIPC
# (Kubernetes v1.30+ with ValidatingAdmissionPolicy + Binding enabled)
# -------------------------
# This further guarantees hostIPC cannot be set even if PSA is loosened later.
# Safe to re-run (create-or-replace semantics).

if kubectl api-resources | grep -q "^validatingadmissionpolicies"; then
echo "ValidatingAdmissionPolicy API detected - creating hostIPC deny policy."

cat <<'EOF' | kubectl apply -f -
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: deny-hostipc
spec:
paramKind: {}
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE","UPDATE"]
resources: ["pods"]
validations:
- expression: "!(object.spec.hostIPC == true)"
message: "Pods must not set spec.hostIPC: true"
reason: Forbidden
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: deny-hostipc-binding
spec:
policyName: deny-hostipc
validationActions: ["Deny"]
EOF

else
echo "ValidatingAdmissionPolicy API not available; relying on PodSecurity labels only."
fi

# -------------------------
# Verification
# -------------------------
echo "Verifying no pods are currently using hostIPC..."

result="$(kubectl get pods --all-namespaces -o json | jq -r 'if any(.items[]?; .spec.hostIPC == true) then "HOSTIPC_FOUND" else "NO_HOSTIPC" end')"

if [[ "$result" == "NO_HOSTIPC" ]]; then
echo "Verification passed: NO_HOSTIPC"
exit 0
else
echo "Verification failed: HOSTIPC_FOUND"
echo "There are existing pods using hostIPC. They were not modified by this script."
echo "List of offending pods:"
kubectl get pods --all-namespaces -o json \
| jq -r '.items[] | select(.spec.hostIPC == true) | [.metadata.namespace, .metadata.name] | @tsv'
exit 1
fi