Restricted Pod Security Admission Labels Leave Already-Running Kubernetes Pods Unprotected
A namespace label that looks like enforced hardening only governs admission of new or updated pods; pods already running keep whatever privileges they had before the label was applied.
Operational summary
At a glance
- Symptom
- A namespace is labelled pod-security.kubernetes.io/enforce=restricted, a security review confirms the label is present, yet a subsequent audit finds privileged pods with host namespace access…
- Likely cause
- Pod Security Admission is an admission controller.
- Impact
- Privileged or otherwise non-compliant pods continue running with elevated container capabilities, host access or unrestricted security contexts indefinitely, while security tooling and change logs record the namespace as…
- Verification signal
- Validate success by confirming both the namespace policy and the live pod state agree.kubectl get pods -n -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged==true)'This query should return no…
- Safe correction
- Correcting the gap requires making the existing workloads pass through admission again, not simply trusting the label.
- Rollback or recovery
- Rollback applies to the deployment restart, not to the namespace label.
Symptom
A namespace is labelled pod-security.kubernetes.io/enforce=restricted, a security review confirms the label is present, yet a subsequent audit finds privileged pods with host namespace access, root containers or hostPath mounts still running in that same namespace weeks later.
Nothing in the cluster reports an error. No admission denial events appear for the existing workloads. The dashboard shows the namespace as “policy: restricted” while non-compliant pods keep serving traffic.
False Assumption
Teams applying the label assume that Pod Security Admission behaves like a continuous compliance scanner: that adding the enforce label causes Kubernetes to walk existing pods in the namespace and evict or flag anything that violates the restricted profile. This assumption is understandable because many policy tools (network policies, resource quotas at reconciliation time) do apply retroactively to some degree, and vendor dashboards often summarise namespace posture as if it reflects live workload state.
Root Cause
Pod Security Admission is an admission controller. Admission controllers only evaluate objects at the point of a create or update API call. Kubernetes documentation on security concepts confirms that authorisation and policy controls operate as gatekeepers on API requests, not as background reconciliation loops against existing objects. Once a pod object already exists in etcd and is running, changing a namespace label does not trigger any new admission review of that pod. The pod is simply never re-submitted to the API server, so the restricted policy has nothing to evaluate against it.
The result is a namespace where the label is entirely truthful about future behaviour and entirely silent about present state.
Impact
Privileged or otherwise non-compliant pods continue running with elevated container capabilities, host access or unrestricted security contexts indefinitely, while security tooling and change logs record the namespace as hardened. This gap is most damaging immediately after a security remediation sprint, when reviewers close out an action item on the strength of the label rather than on the state of running workloads, and it persists until something else forces those specific pods to be recreated.
Diagnosis
Confirm the gap with read-only checks before changing anything:
kubectl get ns --show-labels | grep pod-security.kubernetes.io
kubectl get pods -n <namespace> -o json | jq '.items[] | {name:.metadata.name, hostNetwork:.spec.hostNetwork, privileged:[.spec.containers[].securityContext.privileged]}'
Cross-check pod creation timestamps against the label application time recorded in your change log or audit trail. Pods created before the label was set, and never updated since, are the ones at risk. If your cluster has API audit logging enabled, search for admission decisions on those specific pod names around the label change window; the absence of any decision confirms no re-evaluation occurred.
Correction
Correcting the gap requires making the existing workloads pass through admission again, not simply trusting the label. First, run the namespace in warn and audit mode alongside enforce so violations are surfaced without immediately blocking anything:
kubectl label ns <namespace> pod-security.kubernetes.io/warn=restricted pod-security.kubernetes.io/audit=restricted --overwrite
Review the resulting warnings and audit annotations against your workload inventory. For each deployment that owns a non-compliant pod, trigger a rolling recreation so the new pod specs are actually submitted to the API server and evaluated against the restricted profile:
kubectl rollout restart deployment/<name> -n <namespace>
This is a state-changing action. Scope it to one deployment at a time, confirm the deployment has a healthy previous revision, and only proceed once you have a rollback path ready (below). Stop immediately if the restart produces a CrashLoopBackOff or if the new pod is rejected by admission and no compliant replacement becomes ready within your expected rollout window; investigate the admission denial message before retrying.
Validation
Validate success by confirming both the namespace policy and the live pod state agree.
kubectl get pods -n <namespace> -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged==true)'
This query should return no results once remediation is complete. Additionally, use a server-side dry run against a deliberately non-compliant pod spec to confirm enforcement is genuinely active for new submissions:
kubectl apply --dry-run=server -f privileged-test-pod.yaml -n <namespace>
Expect this dry run to be rejected with a Pod Security Admission denial referencing the restricted profile. A rejection here, combined with an empty result from the privileged-pod query, is the pass condition for this remediation.
Rollback
Rollback applies to the deployment restart, not to the namespace label. If the rolling recreation degrades service availability or the new pod fails to reach a ready state within your defined window, revert the deployment to its previous revision:
kubectl rollout undo deployment/<name> -n <namespace>
Confirm rollback success with kubectl rollout status deployment/<name> -n <namespace> and re-check pod readiness. Rolling back restores the prior pod, which will again be non-compliant with the restricted profile; treat this as a return to the original detection state, not as a resolved condition, and re-open the remediation with a smaller batch size or corrected workload spec.
Prevention
Treat a namespace policy label as a statement about future admissions only. To close the gap between label and live state: run a scheduled read-only audit that diffs the restricted profile against currently running pod specs, independent of admission events; require that any namespace policy change be paired with a tracked task to recreate existing workloads in that namespace; and prefer policy engines such as Kyverno or OPA Gatekeeper that support explicit background scanning of existing resources if continuous enforcement against already-running pods is a requirement, rather than relying on Pod Security Admission alone for that purpose.
Apply the safer control
Before you change production
Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.
Fix commands and configuration
pod-security.kubernetes.io/enforce=restrictedkubectl get ns --show-labels | grep pod-security.kubernetes.iokubectl get pods -n <namespace> -o json | jq '.items[] | {name:.metadata.name, hostNetwork:.spec.hostNetwork, privileged:[.spec.containers[].securityContext.privileged]}'Verify, roll back or escalate
Verify
Validate success by confirming both the namespace policy and the live pod state agree.kubectl get pods -n <namespace> -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged==true)'This query should return no results once remediation is complete.
Rollback
Rollback applies to the deployment restart, not to the namespace label.
Escalate
Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.