fix(kubescape): except C-0007 delete-capable RBAC by object, not namespace#2446
fix(kubescape): except C-0007 delete-capable RBAC by object, not namespace#2446devantler wants to merge 4 commits into
Conversation
…space
Control C-0007 ("Roles with delete capabilities") is exempted only via
controller-rbac.yaml's namespaceSelector, which cannot match RBAC
findings: Kubescape keys them on the Role/ClusterRole/binding object, and
19 of C-0007's 26 findings terminate on cluster-scoped ClusterRoleBindings
whose namespace is empty. So the exception is a silent no-op and every
delete-capable controller renders failed.
Move C-0007 to a kind+name resources match (new delete-rbac.yaml),
mirroring wildcard-rbac.yaml / C-0187 — the proven mechanism for RBAC
objects. Matches each of the 26 delete-capable bindings by kind+name so
C-0007 still flags any new/accidental delete grant. Mirror the change in
the Headlamp plugin ConfigMap (which keys on the owning SA's namespace).
Depends on the scanner-mount fix (config.json postRenderer) landing first
before it can take effect on the in-cluster scan.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
📜 Recent review details🧰 Additional context used📓 Path-based instructions (4)**/*.{yaml,yml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
k8s/**📄 CodeRabbit inference engine (AGENTS.md)
Files:
k8s/bases/infrastructure/**📄 CodeRabbit inference engine (AGENTS.md)
Files:
k8s/bases/infrastructure/**/*.{yaml,yml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (2)📚 Learning: 2026-07-01T21:13:36.950ZApplied to files:
📚 Learning: 2026-07-04T13:30:04.759ZApplied to files:
🔇 Additional comments (3)
📝 WalkthroughWalkthroughThis PR moves Kubescape control C-0007 handling into a dedicated exception manifest that matches specific RBAC bindings by kind and name, removes the old ignore entry from controller-rbac, adds the new manifest to the base kustomization, and updates the Headlamp exception config to mirror the new policy. Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@k8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yaml`:
- Around line 38-124: The Crossplane provider ClusterRoleBinding exception is
pinned to a revision-specific literal name, so it will break on the next
provider reinstall. Update the delete-rbac exception entry in the
ClusterRoleBinding section to match the provider binding by a stable pattern or
selector-based approach instead of the exact hashed name, so the rule continues
to apply across provider churn.
In
`@k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml`:
- Around line 92-119: The delete-capable-rbac-by-design exception is matching by
namespace, which misses cluster-scoped RBAC bindings seen by delete-rbac.yaml.
Update the postureExceptionPolicy entry in the config-map-headlamp-exceptions
manifest to mirror the same RBAC object targeting used by the delete-rbac logic,
using kind+name matches for ClusterRoleBinding and RoleBinding instead of
relying on namespace, while preserving the explicit crossplane-masters Group
rule.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 14faa482-258c-4ce9-becc-f084c63cf4f9
📒 Files selected for processing (4)
k8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/kustomization.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{yaml,yml}: Use Kustomize overlays rather than editing base resources directly;k8s/bases/is immutable from overlays and changes should be made withpatches:in provider or cluster overlays.
Keep manifest changes small and use YAML/schema validation before submitting a manifest PR; for files with cluster context, preferksail workload validate/kubectl kustomize/kubectl apply --dry-run=clientas appropriate.
Files:
k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yamlk8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
k8s/**
📄 CodeRabbit inference engine (AGENTS.md)
k8s/**: Respect Flux dependency order:bootstrap→infrastructure-controllers→infrastructure→apps, with the prod-onlyinfrastructure-overprovisioninglayer hanging offinfrastructurewithout gatingapps.
Follow the hierarchical Kustomization flow: base configurations ink8s/bases/feed provider overlays ink8s/providers/, which feed cluster overlays ink8s/clusters/.
Files:
k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yamlk8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
k8s/bases/infrastructure/**
📄 CodeRabbit inference engine (AGENTS.md)
k8s/bases/infrastructure/**: Underk8s/bases/infrastructure/, organize resources component-folder-first: a component's HelmRelease/HelmRepository and its own CRs should live together in a folder named after the component unless a split is required.
Split a custom resource into its own plural-Kind folder only when it cannot live with its component, such as for CRD dependency ordering or because it is cluster-scoped/cross-cutting.
Files:
k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yamlk8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
k8s/bases/infrastructure/**/*.{yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
k8s/bases/infrastructure/**/*.{yaml,yml}: For component-folder files, name manifests after the resource Kind in kebab-case; if a folder contains multiple resources of the same Kind, qualify filenames with a purpose suffix.
For CR-folder files, omit the folder-implied Kind from the filename and use theverb-purpose.yamlform.
Name FluxKustomizationresourcesflux-kustomization*.yaml; keep the kustomize build file named exactlykustomization.yaml.
Files:
k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yamlk8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
🧠 Learnings (1)
📚 Learning: 2026-07-01T21:13:36.950Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2359
File: k8s/bases/apps/actual-budget/helm-release.yaml:62-111
Timestamp: 2026-07-01T21:13:36.950Z
Learning: When reviewing Kustomize/Helm YAML in this repo, keep the base vs provider overlay split: `k8s/bases/apps/**` and `k8s/bases/infrastructure/**` should contain each app’s full, environment-agnostic configuration (including base-level postRenderer Kustomize patches such as deployment strategy, topology spread, probes, and env injection). `k8s/providers/{docker,hetzner}/**` should only add small provider-specific deltas (e.g., `interval`, `persistence.size`) via patch files (like `k8s/providers/<provider>/apps/<app>/patches/helm-release-patch.yaml`). If configuration is identical across providers (e.g., OIDC/OAuth env vars where `${domain}` is resolved per cluster via envsubst), it belongs in the base and must not be duplicated into provider overlays.
Applied to files:
k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yamlk8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
🔇 Additional comments (3)
k8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yaml (1)
38-50: LGTM!k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yaml (1)
8-8: LGTM!k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml (1)
72-90: LGTM!
…ttern Exception names are regex-compared, so the provider-revision hash can be matched by pattern instead of pinned — the entry survives provider re-installs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mp exceptions C-0007 findings terminate on the binding objects (19 of 26 cluster-scoped, namespace empty), so the namespace designator never covered them — mirror the CSE's kind+name matches instead, keeping the crossplane-masters Group. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml (1)
49-471: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider validating the embedded JSON blob before merge.
This is a large hand-maintained JSON string inside a YAML block scalar; a stray comma or missing bracket would silently break exception application (Headlamp would just show no exceptions) without any schema error surfacing at the Kustomize layer.
🔍 Suggested verification script
#!/bin/bash # Extract the `exceptionPolicies` block scalar value and validate as JSON. python3 - <<'EOF' import yaml, json with open("k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml") as f: doc = yaml.safe_load(f) raw = doc["data"]["exceptionPolicies"] json.loads(raw) print("Valid JSON, entries:", len(json.loads(raw))) EOF🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml` around lines 49 - 471, The embedded exceptionPolicies JSON blob needs validation before merge to catch syntax mistakes that would make Headlamp load no exceptions. Add a verification step that parses the YAML block scalar from the config map and JSON-decodes it, using the data.exceptionPolicies field as the target. If possible, wire this check into CI or a pre-merge script so any stray comma or missing bracket in the postureExceptionPolicy entries is caught early.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml`:
- Around line 49-471: The embedded exceptionPolicies JSON blob needs validation
before merge to catch syntax mistakes that would make Headlamp load no
exceptions. Add a verification step that parses the YAML block scalar from the
config map and JSON-decodes it, using the data.exceptionPolicies field as the
target. If possible, wire this check into CI or a pre-merge script so any stray
comma or missing bracket in the postureExceptionPolicy entries is caught early.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 8a3f06af-e80a-484f-8b76-e9b9ceaf1817
📒 Files selected for processing (2)
k8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yamlk8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
- k8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yaml
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{yaml,yml}: Use Kustomize overlays rather than editing base resources directly;k8s/bases/is immutable from overlays and changes should be made withpatches:in provider or cluster overlays.
Keep manifest changes small and use YAML/schema validation before submitting a manifest PR; for files with cluster context, preferksail workload validate/kubectl kustomize/kubectl apply --dry-run=clientas appropriate.
Files:
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
k8s/**
📄 CodeRabbit inference engine (AGENTS.md)
k8s/**: Respect Flux dependency order:bootstrap→infrastructure-controllers→infrastructure→apps, with the prod-onlyinfrastructure-overprovisioninglayer hanging offinfrastructurewithout gatingapps.
Follow the hierarchical Kustomization flow: base configurations ink8s/bases/feed provider overlays ink8s/providers/, which feed cluster overlays ink8s/clusters/.
Files:
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
k8s/bases/infrastructure/**
📄 CodeRabbit inference engine (AGENTS.md)
k8s/bases/infrastructure/**: Underk8s/bases/infrastructure/, organize resources component-folder-first: a component's HelmRelease/HelmRepository and its own CRs should live together in a folder named after the component unless a split is required.
Split a custom resource into its own plural-Kind folder only when it cannot live with its component, such as for CRD dependency ordering or because it is cluster-scoped/cross-cutting.
Files:
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
k8s/bases/infrastructure/**/*.{yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
k8s/bases/infrastructure/**/*.{yaml,yml}: For component-folder files, name manifests after the resource Kind in kebab-case; if a folder contains multiple resources of the same Kind, qualify filenames with a purpose suffix.
For CR-folder files, omit the folder-implied Kind from the filename and use theverb-purpose.yamlform.
Name FluxKustomizationresourcesflux-kustomization*.yaml; keep the kustomize build file named exactlykustomization.yaml.
Files:
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
🧠 Learnings (2)
📚 Learning: 2026-07-01T21:13:36.950Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2359
File: k8s/bases/apps/actual-budget/helm-release.yaml:62-111
Timestamp: 2026-07-01T21:13:36.950Z
Learning: When reviewing Kustomize/Helm YAML in this repo, keep the base vs provider overlay split: `k8s/bases/apps/**` and `k8s/bases/infrastructure/**` should contain each app’s full, environment-agnostic configuration (including base-level postRenderer Kustomize patches such as deployment strategy, topology spread, probes, and env injection). `k8s/providers/{docker,hetzner}/**` should only add small provider-specific deltas (e.g., `interval`, `persistence.size`) via patch files (like `k8s/providers/<provider>/apps/<app>/patches/helm-release-patch.yaml`). If configuration is identical across providers (e.g., OIDC/OAuth env vars where `${domain}` is resolved per cluster via envsubst), it belongs in the base and must not be duplicated into provider overlays.
Applied to files:
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
📚 Learning: 2026-07-04T13:30:04.759Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2446
File: k8s/bases/infrastructure/cluster-security-exceptions/delete-rbac.yaml:38-125
Timestamp: 2026-07-04T13:30:04.759Z
Learning: For Kubescape ClusterSecurityException (apiVersion kubescape.io/v1beta1) and the mirrored Headlamp exception config, do NOT pin `spec.match.resources[].name` (and Headlamp `attributes.name`) to a single literal value when the identifier includes a generated hash. These fields are compared using `regexCompare`, so match such resources with an anchored regular expression that covers the stable prefix and the hash pattern (e.g., `^crossplane:provider:provider-upjet-github-[0-9a-f]+:system$`) rather than the current hash, so the exception remains valid across provider re-installs/revisions.
Applied to files:
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
🔇 Additional comments (1)
k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml (1)
92-127: LGTM!
Review-body nitpick resolution record (no thread exists for it): validate the embedded JSON blob — verified against the current head: |
…7-rbac-exception # Conflicts: # k8s/bases/infrastructure/cluster-security-exceptions/controller-rbac.yaml # k8s/bases/infrastructure/cluster-security-exceptions/kustomization.yaml # k8s/bases/infrastructure/controllers/kubescape/config-map-headlamp-exceptions.yaml
CodeRabbit body-finding resolution record (🧹 Nitpick, config-map-headlamp-exceptions.yaml: validate the embedded JSON blob / wire a CI check):
|
Resolution record for the CodeRabbit review-body nitpick (2026-07-04 13:32Z review — no inline thread exists): Validate the embedded JSON blob before merge — verified against the current head: |
Why
Control C-0007 "Roles with delete capabilities" shows every one of its 26 legitimate infra-controller / tenant service accounts (Flux, Velero, Longhorn, CNPG, Kyverno, cert-manager, KubeVirt, Crossplane…) as failing. Its exception used a namespace match, which Kubescape ignores for RBAC findings — 19 of the 26 are cluster-scoped bindings with no namespace at all — so the exception never applied.
What
Move C-0007 to the kind+name match that actually works for RBAC objects: a new
delete-rbac.yamlmatching each delete-capable binding, plus the mirrored Headlamp ConfigMap change. This is the same pattern and same 4 files as the sibling per-control PRs (#2442 C-0015, #2440 C-0002, #2434 C-0026) — it fills the missing C-0007 case (the largest, at 26 findings). The list stays explicit so a new/accidental delete grant is still flagged; two churn-prone entries (the Crossplane provider revision hash, the on-demand tofu-runner) are flagged inline for periodic refresh.Sequencing: takes effect only after #2443 (the
keepLocalscan-persistence fix) unfreezes in-cluster scanning — reconcile the binding list against a fresh scan then. Shares files with #2442/#2440/#2434, so whichever merges after the first needs a trivial rebase. Related: #2264.