Skip to main content

Enforce Pod Security Standard Baseline Profile Or Stricter

More Info:

Pod Security Admission should enforce at least the Baseline profile on every namespace containing user workloads to block privileged and unsafe pod configurations. Namespaces without an enforce label are unprotected.

Risk Level

Critical

Address

Security

Compliance Standards

  • CIS GKE

Triage and Remediation

Remediation

Manual Steps
  1. On any machine with kubectl access, list all namespaces and see which already have an enforce label (and what level it is set to):

    kubectl get ns --show-labels

    Focus on the pod-security.kubernetes.io/enforce label; note any namespaces with privileged, baseline, restricted, or no value.

  2. Identify namespaces that currently enforce a profile weaker than Baseline or have no enforce label:

    kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\n"}' \
    | sort

    From this list, mark:

    • Namespaces with empty (no label) or missing value.
    • Namespaces with privileged (weaker than Baseline).
    • Exclude known system/control-plane namespaces if your policy allows different treatment there (e.g. kube-system, kube-public, kube-node-lease, provider-specific system namespaces).
  3. For each remaining (non-system) namespace, determine whether it hosts user workloads:

    for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}'); do
    echo "### $ns"
    kubectl get pods -n "$ns" --no-headers 2>/dev/null | head
    echo
    done

    Alternatively, check selectively for any candidate namespace from step 2:

    kubectl get pods -n <namespace> -o wide

    Treat any namespace running business applications, batch jobs, or user-facing services as a “user workload” namespace.

  4. For each namespace that both (a) contains user workloads and (b) lacks an adequate enforce label (none/privileged), decide the target profile:

    • Minimum: baseline (per remediation).
    • Prefer restricted if workloads are known to be hardened and compatible.
      Before changing, confirm with application owners whether their workloads depend on privileged containers, hostPath volumes, host networking, or other disallowed settings under Baseline/Restricted.
  5. Apply or adjust the enforce label using kubectl on each chosen namespace (any machine with kubectl access):

    • To enforce Baseline (minimum required):
      kubectl label namespace <namespace> pod-security.kubernetes.io/enforce=baseline --overwrite
    • To enforce a stricter Restricted profile (if suitable):
      kubectl label namespace <namespace> pod-security.kubernetes.io/enforce=restricted --overwrite

    Be aware: once set, new non-compliant Pods in that namespace will be rejected. Existing Pods keep running but may fail on restart if non-compliant.

  6. Verify that all user-workload namespaces now enforce at least Baseline:

    kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\n"}' \
    | sort

    Optionally, rerun the original audit to confirm the delta between Baseline-enforced namespaces and all namespaces, then manually confirm that any remaining unlabelled namespaces indeed do not contain user workloads or are intentionally exempt:

    diff \
    <(kubectl get namespace -l pod-security.kubernetes.io/enforce=baseline -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}') \
    <(kubectl get namespace -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}')
Using kubectl
# 1) List all namespaces and show their Pod Security enforce level
# Run on: any machine with kubectl access
kubectl get ns \
-o custom-columns='NAME:.metadata.name,ENFORCE:.metadata.labels.pod-security\.kubernetes\.io/enforce' \
--sort-by=.metadata.name
  • Problem indication: Any namespace that runs or may run user workloads where ENFORCE is empty/<none> or weaker than your policy (e.g., privileged when you require baseline or restricted).
# 2) Show only namespaces that currently have NO enforce label
# Run on: any machine with kubectl access
kubectl get ns \
-o jsonpath='{range .items[?(!@.metadata.labels.pod-security\.kubernetes\.io/enforce)]}{.metadata.name}{"\n"}{end}'
  • Problem indication: Any listed namespace that hosts user workloads (applications, jobs, CI workloads, etc.) needs human review; if they should be protected, they are currently unprotected by Pod Security Admission.
# 3) Compare enforced-baseline namespaces vs all namespaces (audit-equivalent)
# Run on: any machine with kubectl access
diff \
<(kubectl get ns -l pod-security.kubernetes.io/enforce=baseline -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}') \
<(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}')
  • Problem indication: Any lines starting with > are namespaces that do not have pod-security.kubernetes.io/enforce=baseline. For each of those, a human must decide:
    • Does this namespace contain or will it contain user workloads?
    • If yes, should it enforce baseline or a stricter profile (restricted), or be exempt for a clear reason?
# 4) Inspect workload types in a specific namespace (replace with a candidate from above)
# Run on: any machine with kubectl access
NAMESPACE=example-namespace

kubectl get deploy,statefulset,daemonset,job,cronjob,pod -n "$NAMESPACE" \
-o custom-columns='KIND:.kind,NAME:.metadata.name' 2>/dev/null
  • Problem indication: If this shows user workloads and the namespace lacks an appropriate pod-security.kubernetes.io/enforce label (or is weaker than your policy), that namespace is in scope for remediation.
Automation
#!/usr/bin/env bash
# Purpose: Report namespaces that do NOT have Pod Security Admission enforce label
# Scope: Run on any machine with kubectl access and correct context

set -euo pipefail

echo "=== Pod Security Admission enforce label report (baseline or stricter) ==="
echo

echo "Kubernetes context:"
kubectl config current-context
echo

echo "All namespaces and their enforce labels:"
kubectl get ns -o custom-columns='NAME:.metadata.name,ENFORCE:.metadata.labels.pod-security\.kubernetes\.io/enforce' | sort
echo

echo "Namespaces missing an enforce label (UNPROTECTED):"
kubectl get ns \
-o jsonpath='{range .items[?(!@.metadata.labels.pod-security\.kubernetes\.io/enforce)]}{.metadata.name}{"\n"}{end}' \
| sort || true
echo

echo "Namespaces with enforce=baseline (MEETS MINIMUM):"
kubectl get ns -l pod-security.kubernetes.io/enforce=baseline \
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| sort || true
echo

echo "Namespaces with enforce=strict (EXCEEDS MINIMUM):"
kubectl get ns -l pod-security.kubernetes.io/enforce=strict \
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| sort || true
echo

cat <<'EOF'

How to interpret this report:
- Any namespace listed under "Namespaces missing an enforce label (UNPROTECTED)"
does NOT have Pod Security Admission enforce policy set and should be reviewed.
- For namespaces that contain user workloads:
- They should NOT appear as UNPROTECTED.
- They should appear under either:
- "Namespaces with enforce=baseline (MEETS MINIMUM)", or
- "Namespaces with enforce=strict (EXCEEDS MINIMUM)".

This check is MANUAL:
- You must decide, per namespace, whether it hosts user workloads and whether
applying an enforce label is safe for existing pods and controllers.
- To remediate a chosen namespace (example: my-namespace), run:

kubectl label namespace my-namespace pod-security.kubernetes.io/enforce=baseline --overwrite

EOF