docs(security): size the declared over-reach of the pod-security exception - #3063
Conversation
…ption The annotation understated the exception's scope: add-pod-security-context excludes three namespaces (cert-manager, keda, opencost) beyond the twelve recorded, and C-0211 is exempted in no other CR, so it is uncovered wherever the mutation is absent. Record the measured surface so the residual risk is sized rather than open ended. Part of #2824
✅
|
CI is green at this head and the change is comment-only — the generated Kubescape exception is byte-identical, verified by running the generator before and after the edit. Requesting review per lane priority. @coderabbitai review |
|
|
📝 WalkthroughWalkthroughThe pull request adds comments to Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
CodeRabbit is rate limited at this head ( @codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b627b6fefc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…welve-namespace set add-imageuid-pod-security-context matches cert-manager, keda and opencost by name and supplies their pod-level fields, so they are not part of the unmutated set. Scope the measured sizing to C-0013/C-0016/C-0055 and keep C-0211 unsized, since its field set differs and kubescape-privileged.yaml does not cover it. Part of #2824
All three Codex findings are fixed or explicitly refuted, their threads replied to and resolved, and CI is green at this new head. Restarting the loop at CodeRabbit per lane priority — this is a new head, so the earlier rate-limit at @coderabbitai review |
|
|
CodeRabbit is rate limited at this head too ( @codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 230d45b740
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
kubevirt and cdi sit in the set already excepted by infrastructure-privileged, so they were never counted; both have no namespace in prod, as do local-path-storage and chaos-mesh. Half the twelve run no workloads. Mark the counts as a prod-only snapshot. Part of #2824
The fourth finding is fixed and its thread resolved; CI is green at this new head and all four threads are closed. Restarting the loop at CodeRabbit per lane priority — new head, so the earlier rate-limits do not carry over. @coderabbitai review |
|
|
… measured Of the six namespaces that run workloads, four are the excepted set and were never measured; only flux-system and kubescape were. Say so, rather than implying the in-spec finding covers all six. Part of #2824
Self-review found a fifth instance of the same defect, in
|
| # | Claimed over | Actually iterated |
|---|---|---|
| 1 | all mutation rules | only their exclude blocks |
| 2 | four controls | three (C-0211 has a different field set) |
| 3 | twelve namespaces | the six uncovered ones |
| 4 | four empty namespaces | six are empty; four have no namespace at all |
| 5 | six namespaces with workloads | the two genuinely uncovered ones |
Four of the five were caught by review rather than by me, on a comment-only change. The measurement
underneath was sound each time; the writing-up kept outrunning it. The check that would have caught
all five is cheap and grammatical — name the set you iterated, name the set the sentence quantifies
over, and prove they are the same set — and it is now recorded in my own operating notes as a
pre-publication step for any counted claim.
Readiness on this PR is otherwise unchanged: CI green, generated Kubescape exception byte-identical
on every push (verified five times), all threads resolved.
Self-review fix pushed; CI is green at this head and all threads are resolved. Restarting the loop at CodeRabbit per lane priority. @coderabbitai review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== Commit and changed files =='
git show --no-ext-diff --format=fuller --stat HEAD
git diff --no-ext-diff HEAD^ HEAD --name-status
echo
echo '== Full final commit diff =='
git diff --no-ext-diff --unified=80 HEAD^ HEAD
echo
echo '== Candidate security and generator files =='
fd -t f . | rg -i '(kubescape|pod-security|pod.?security|exception|infrastructure-privileged|generator)'
echo
echo '== References to controls, measured namespaces, and mutation rules =='
rg -n -i -C 4 'C-0013|C-0016|C-0055|C-0211|kube-system|longhorn-system|observability|velero|cert-manager|keda|opencost|mutat' . \
-g '!**/.git/**' -g '!**/node_modules/**' -g '!**/dist/**'Length of output: 201085 🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="$(gh repo view --json nameWithOwner --jq .nameWithOwner)"
echo "== Pull request metadata =="
gh pr view 3063 --repo "$repo" \
--json number,baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,additions,deletions \
--jq '{number, baseRefName, baseRefOid, headRefName, headRefOid, changedFiles, additions, deletions}'
echo
echo "== Changed files =="
gh api "repos/$repo/pulls/3063/files?per_page=100" --paginate \
--jq '.[] | [.filename, .status, .additions, .deletions] | `@tsv`'
echo
echo "== Pull request diff =="
gh pr diff 3063 --repo "$repo" --patch
echo
echo "== Changed-file content at HEAD =="
gh api "repos/$repo/pulls/3063/files?per_page=100" --paginate --jq -r '.[].filename' |
while IFS= read -r file; do
echo "--- $file ---"
sed -n '1,360p' "$file"
done
echo
echo "== Relevant mutation-policy sections =="
sed -n '1,290p' k8s/bases/infrastructure/cluster-policies/best-practices/add-security-context.yamlLength of output: 17483 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== Final PR file with line numbers =='
nl -ba k8s/bases/infrastructure/cluster-security-exceptions/pod-security-mutations.yaml | sed -n '1,220p'
echo
echo '== Final PR diff against the PR base =='
git diff --no-ext-diff --unified=100 \
ed1c2d7429d1fd5952d52c0de0d6ac47cda7e5f7 HEAD -- \
k8s/bases/infrastructure/cluster-security-exceptions/pod-security-mutations.yaml
echo
echo '== Related exception files =='
for file in \
k8s/bases/infrastructure/cluster-security-exceptions/infrastructure-privileged.yaml \
k8s/bases/infrastructure/cluster-security-exceptions/kubescape-privileged.yaml
do
if [ -f "$file" ]; then
echo "--- $file ---"
nl -ba "$file" | sed -n '1,260p'
else
echo "MISSING: $file"
fi
done
echo
echo '== Mutation rules and exact namespace matching =='
nl -ba k8s/bases/infrastructure/cluster-policies/best-practices/add-security-context.yaml | sed -n '90,285p'
echo
echo '== All definitions of the related exception resources =='
rg -n -i -C 5 'infrastructure-privileged|kubescape-privileged|pod-security-mutations' \
k8s/bases/infrastructure/cluster-security-exceptionsLength of output: 1538 🏁 Script executed: #!/bin/bash
set -euo pipefail
numbered() {
awk '{ printf "%6d\t%s\n", NR, $0 }' "$1"
}
echo '== Final PR file with line numbers =='
numbered k8s/bases/infrastructure/cluster-security-exceptions/pod-security-mutations.yaml | sed -n '1,220p'
echo
echo '== Final PR diff against the PR base =='
git diff --no-ext-diff --unified=100 \
ed1c2d7429d1fd5952d52c0de0d6ac47cda7e5f7 HEAD -- \
k8s/bases/infrastructure/cluster-security-exceptions/pod-security-mutations.yaml
echo
echo '== Related exception files =='
for file in \
k8s/bases/infrastructure/cluster-security-exceptions/infrastructure-privileged.yaml \
k8s/bases/infrastructure/cluster-security-exceptions/kubescape-privileged.yaml
do
if [ -f "$file" ]; then
echo "--- $file ---"
numbered "$file" | sed -n '1,260p'
else
echo "MISSING: $file"
fi
done
echo
echo '== Mutation rules and exact namespace matching =='
numbered k8s/bases/infrastructure/cluster-policies/best-practices/add-security-context.yaml | sed -n '90,285p'
echo
echo '== All definitions of the related exception resources =='
rg -n -i -C 5 'infrastructure-privileged|kubescape-privileged|pod-security-mutations' \
k8s/bases/infrastructure/cluster-security-exceptionsLength of output: 35420
I found no actionable issues. The annotation now matches the mutation rules and the related exceptions. It correctly limits the measured C-0013/C-0016/C-0055 claim to ✅ Action performedReview finished.
|
Readiness record1. Programmatically tested. 2. Reviewed. CodeRabbit at the current head: "Reviewed 3. Tried and evaluated as a user. The consumer of this file is The substance was verified against the running prod cluster rather than the manifests alone: namespace Promoting and merging. |

Why
The cluster-wide pod-security exception is deliberately wider than its own justification, and its
annotation is the only record of that. The record was not sized, so the residual risk could not be
judged from the file — which is what kept the exception "declared" rather than narrowed.
What
Sizes the exposure from a live measurement, so the declaration is reviewable rather than open ended.
everywhere except three Deployments — so the remediation is small and known.
name-scoped exception does not cover it. Sizing it needs its own pass.
cert-manager,kedaandopencostare mutated by a different rule, so afuture reader does not mistake them for uncovered.
Comment-only — the generated Kubescape exception is byte-identical, verified by running the generator
before and after each push, so posture and the CI gate are unchanged.
Remediation tracked in #3064. Part of #2824