You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
add-baseline-context-optin-* supplies fsGroupChangePolicy and an effective SELinux level to pods in opted-in namespaces, and it demonstrably works β velero's pods carry both fields and none failed to start. But Kyverno mutates the pod at admission, while Kubescape scores the stored workload spec. Settled with evidence on #3239 (2026-09-02): each scan object is keyed to the workload, not a pod (deployment-velero carries wlid://cluster-prod/namespace-velero/deployment-velero, kubescape.io/workload-kind: Deployment, relatedObjects: null), and the exception's own reason field has always said so β "Kubescape scans the stored spec, not the live pod."
velero is the natural experiment: opted in, its pods measurably carry both fields, its template carries neither, and the scan object is the Deployment's.
So no amount of widening the namespace opt-in can move a template-scored verdict. Re-measured live against prod stored specs on 2026-09-02:
field (pod level, stored spec)
absent on
fsGroupChangePolicy
35 / 35
effective SELinux level on every container
35 / 35
fsGroup
20 / 35
runAsGroup
26 / 35
runAsNonRoot
19 / 35
Population is 35 workloads across the four scanned excluded namespaces β 17 Deployments, 8 DaemonSets, 7 CronJobs, 3 StatefulSets (flux-system 6, longhorn-system 12, observability 15, velero 2).
Audience and problem
The pod-security-mutations-unscoped exception suppresses C-0211 across this population, so every workload reports passed w/exceptions regardless of its actual state. That exception is waiting to be narrowed, and it cannot narrow while the underlying templates still fail β which, on the scanned surface, all 35 do. The admission-time mutation improves runtime posture and can never discharge the exception.
Hypothesis
Patching the two non-privilege fields into the workload templates at source β chart values where the chart exposes them, kustomize patches where it does not β moves the scanned verdict for those two controls, after which C-0211's residual shrinks to the workloads that still fail on the genuinely privilege-adjacent fields (fsGroup, runAsGroup, runAsNonRoot) and narrowing the exception becomes sizable rather than all-or-nothing.
Deliberately not in scope: fsGroup, runAsGroup, runAsNonRoot. Those are the fields the namespace exclusions exist to protect, and supplying them is a privilege change, not a compliance one.
Guardrail: no workload regressed on privilege, user or group fields, and no pod sandbox failing to start.
Smallest useful change
One namespace, smallest first: velero (2 workloads). It is already opted in, so the pod-scope and template-scope effects can be compared directly on the same workloads β which also proves the measurement method before it is applied to the other 33.
Acceptance criteria
The two non-privilege fields are present in the stored spec of the targeted workloads, via chart values or kustomize patches, not via admission mutation.
Verified by a single-object GET of the workload's workloadconfigurationscans object β a LIST returns .spec.controls null and would read as a clean sweep.
subStatus is used to distinguish a genuine pass from a suppressed one.
No regression on privilege, user or group fields; pods still start.
The C-0211 residual recorded in pod-security-mutations-unscoped.yaml is updated to the new figure, re-measured rather than inherited.
Size
Medium, and naturally decomposable per namespace. The investigation is already done β #3239 carries it β so what remains is the mechanical work plus its measurement.
Follow-up to #3239, which established that admission-time mutation cannot move this surface. The two are complementary, not alternatives: the mutation stays for runtime posture, this is the narrowing path.
Evidence
add-baseline-context-optin-*suppliesfsGroupChangePolicyand an effective SELinuxlevelto pods in opted-in namespaces, and it demonstrably works βvelero's pods carry both fields and none failed to start. But Kyverno mutates the pod at admission, while Kubescape scores the stored workload spec. Settled with evidence on #3239 (2026-09-02): each scan object is keyed to the workload, not a pod (deployment-velerocarrieswlid://cluster-prod/namespace-velero/deployment-velero,kubescape.io/workload-kind: Deployment,relatedObjects: null), and the exception's ownreasonfield has always said so β "Kubescape scans the stored spec, not the live pod."velerois the natural experiment: opted in, its pods measurably carry both fields, its template carries neither, and the scan object is the Deployment's.So no amount of widening the namespace opt-in can move a template-scored verdict. Re-measured live against prod stored specs on 2026-09-02:
fsGroupChangePolicylevelon every containerfsGrouprunAsGrouprunAsNonRootPopulation is 35 workloads across the four scanned excluded namespaces β 17 Deployments, 8 DaemonSets, 7 CronJobs, 3 StatefulSets (flux-system 6, longhorn-system 12, observability 15, velero 2).
Audience and problem
The
pod-security-mutations-unscopedexception suppresses C-0211 across this population, so every workload reportspassed w/exceptionsregardless of its actual state. That exception is waiting to be narrowed, and it cannot narrow while the underlying templates still fail β which, on the scanned surface, all 35 do. The admission-time mutation improves runtime posture and can never discharge the exception.Hypothesis
Patching the two non-privilege fields into the workload templates at source β chart values where the chart exposes them, kustomize patches where it does not β moves the scanned verdict for those two controls, after which C-0211's residual shrinks to the workloads that still fail on the genuinely privilege-adjacent fields (
fsGroup,runAsGroup,runAsNonRoot) and narrowing the exception becomes sizable rather than all-or-nothing.Deliberately not in scope:
fsGroup,runAsGroup,runAsNonRoot. Those are the fields the namespace exclusions exist to protect, and supplying them is a privilege change, not a compliance one.Success signal
fsGroupChangePolicy; 35 / 35 missing an effective SELinuxlevel.subStatusdiscriminator rather than the barestatusβ a suppressed control readspassedeither way, so the naive read returns a clean result over an unfixed population (this is exactly the fail-open feat(security): document every suppressed control's fail-open, and fail CI when one is notΒ #3517 generalised).Smallest useful change
One namespace, smallest first:
velero(2 workloads). It is already opted in, so the pod-scope and template-scope effects can be compared directly on the same workloads β which also proves the measurement method before it is applied to the other 33.Acceptance criteria
GETof the workload'sworkloadconfigurationscansobject β a LIST returns.spec.controlsnull and would read as a clean sweep.subStatusis used to distinguish a genuine pass from a suppressed one.pod-security-mutations-unscoped.yamlis updated to the new figure, re-measured rather than inherited.Size
Medium, and naturally decomposable per namespace. The investigation is already done β #3239 carries it β so what remains is the mechanical work plus its measurement.
Follow-up to #3239, which established that admission-time mutation cannot move this surface. The two are complementary, not alternatives: the mutation stays for runtime posture, this is the narrowing path.