Skip to content

security(kubescape): supply fsGroupChangePolicy and seLinuxOptions to the namespaces the security-context mutation excludes #3239

Description

@devantler

🤖 Generated by the Agentic Engineer

Remaining engineering work: staged source-owned baseline rollout, tracked by #3636 for the Longhorn UI canary. Interactive read-only production access does not block the normal GitOps deploy path. Full-population remeasurement and C-0211 sizing remain open; no maintainer action is currently requested. Verified 2026-09-06.

Evidence

Sizing C-0211's residual population (#3217, measured 2026-08-19 against live prod specs) found that of
the 33 workloads in the four scanned namespaces add-security-context excludes, two gaps are
universal
:

Field Missing on
spec.template.spec.securityContext.fsGroupChangePolicy 33 / 33
securityContext.seLinuxOptions (every container) 33 / 33

Those two account for the whole population. Every other C-0211 field gap is a strict subset
(fsGroup 20, runAsGroup 18, runAsNonRoot 12).

Audience and problem

The twelve namespaces are excluded from add-security-context because the workloads there require
elevated privileges by design
— that rationale is about privilege, and it is sound. But
fsGroupChangePolicy and seLinuxOptions are not privilege fields:

  • fsGroupChangePolicy: OnRootMismatch controls volume ownership changes; rollout safety depends on
    the workload's existing fsGroup, volume types and reconciling owner. It is not universally inert.
  • The current baseline uses seLinuxOptions: {} only where explicit pod/container options are absent,
    preserving runtime SELinux/MCS defaults and existing explicit options. The historical fixed
    level: s0 proposal is superseded; it must not be restored or described as universally harmless.

So the blanket exclusion is suppressing two controls it never needed to, in order to protect privilege
fields that are a different concern.

Hypothesis

A narrow mutation supplying only fsGroupChangePolicy and seLinuxOptions to the excluded
namespaces would close both universal gaps for all 33 workloads without touching privilege, user, or
group — after which C-0211's residual population drops to the subset that still fails on the
privilege-adjacent fields, and narrowing C-0211 becomes sizable rather than all-or-nothing.

Success signal

  • Baseline: 33 of 33 fail set-fsgroupchangepolicy-value and set-seLinuxOptions.
  • Target: 0 of 33 fail either, with no workload regressed on privilege, user or group fields, and
    no pod sandbox failing to start.
  • Guardrail: the add-security-context comment records a real failure mode here — injecting a
    pod-level runAsGroup with no runAsUser yields the OCI user string ":1000", which containerd
    rejects. Neither field in scope has that coupling, but the rollout must prove it per namespace
    rather than assume it.

Smallest useful change

One namespace first — velero is the smallest (2 workloads) and one of them, velero/node-agent, is
in the population. Verify the two fields land and the pods still start, then widen.

Acceptance criteria

  • A mutation supplies fsGroupChangePolicy and seLinuxOptions to the excluded namespaces, using
    conditional anchors so any chart-set value is preserved.
  • Rolled out behind the feature-flag-first convention and validated in both states.
  • The two universal gaps measure 0 of 33 afterwards, re-measured rather than inherited.
  • pod-security-mutations-unscoped.yaml's C-0211 sizing is updated to the new residual.

Size

Small-to-medium. Note the in-cluster posture surface is not currently producing (#2933, #3024), so
verification must read the live specs directly rather than the posture score.

Part of #3217

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions