Skip to content

security(ci): evaluate the excepted RBAC controls in the posture gate - #3057

Merged
devantler merged 14 commits into
mainfrom
claude/kubescape-gate-framework-coverage-2823
Aug 10, 2026
Merged

security(ci): evaluate the excepted RBAC controls in the posture gate#3057
devantler merged 14 commits into
mainfrom
claude/kubescape-gate-framework-coverage-2823

Conversation

@devantler

@devantler devantler commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

🤖 Generated by the Agentic Engineer

Why

The security gate that protects main was only looking at a fraction of what we
write security exceptions for.

Our justified exceptions cover 76 distinct security controls. The gate scanned a
single framework that checks 17 of them — so findings on the other 59 reached
neither the pass/fail score nor the security alerts. That included every access-control
rule those exception files exist to govern, which is why they have repeatedly
looked ineffective: nothing was measuring them.

What

The gate now checks two frameworks instead of one, bringing 7 of the missing
controls under it — three of which have real findings today. The pass/fail floor
is unchanged, and the combined score sits above it.

Expect more security alerts on this repo. These are pre-existing findings becoming
visible, not new problems introduced here.

One thing worth your judgement: the score's margin over the floor is thinner than
before — 97 against a floor of 95, where the single framework scored 99. That is
the honest cost of measuring more. My own CI run is the real test of whether the
margin holds on the CI runner, which has historically scored differently from a
laptop.

52 excepted controls are in neither framework and stay invisible. That residue is
recorded on the issue rather than fixed here.

Part of #2823

The Kubescape gate scanned one framework (NSA-CISA, 20 controls) while the
ClusterSecurityException CRs name 76. 59 excepted controls were outside the
gate, including every RBAC control those CRs exist to govern, so their findings
reached neither the compliance score nor Code Scanning.

Add MITRE ATT&CK, which evaluates 10 of them. Measured locally on ksail
7.178.20: NSA 99.28, MITRE 96.03, combined 97 against the unchanged floor of 95.

Part of #2823
Self-review caught that the first commit conflated two different counts. MITRE
adds 10 controls to the SCAN (nsa 20, mitre 17, union 30) but only 7 of them are
controls we write exceptions for; the untouched residue is 52, not 49. Names the
seven, and states the distinction so the two numbers are not conflated again.
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

⚠️MegaLinter analysis: Success with warnings

⚠️ BASH / bash-exec - 2 errors
Results of bash-exec linter (version 5.3.9)
See documentation on https://megalinter.io/9.6.0/descriptors/bash_bash_exec/
-----------------------------------------------

✅ [SUCCESS] scripts/check-megalinter-version-drift.sh
✅ [SUCCESS] scripts/dr-rebuild-supersession-guard.sh
❌ [ERROR] scripts/ghcr-auth-lib.sh
    Error: File:[scripts/ghcr-auth-lib.sh] is not executable

✅ [SUCCESS] scripts/guard-cilium-homogeneous-device-rollout.sh
✅ [SUCCESS] scripts/guard-kubescape-gate-frameworks.sh
✅ [SUCCESS] scripts/guard-shared-publish-workflow-pin.sh
✅ [SUCCESS] scripts/megalinter-scan-counts.sh
✅ [SUCCESS] scripts/normalize-sarif-paths.sh
❌ [ERROR] scripts/refresh-flux-ghcr-auth-safety.sh
    Error: File:[scripts/refresh-flux-ghcr-auth-safety.sh] is not executable

✅ [SUCCESS] scripts/refresh-flux-ghcr-auth.sh
✅ [SUCCESS] scripts/report-cilium-rollout-gate-suppression.sh
✅ [SUCCESS] scripts/run-ksail-prod-with-pull-auth.sh
✅ [SUCCESS] scripts/summarize-sarif-findings.sh
✅ [SUCCESS] scripts/tests/test-check-megalinter-version-drift.sh
✅ [SUCCESS] scripts/tests/test-cilium-bandwidth-manager-component.sh
✅ [SUCCESS] scripts/tests/test-cilium-homogeneous-devices-activation.sh
✅ [SUCCESS] scripts/tests/test-cilium-homogeneous-devices-autoscaler-gate.sh
✅ [SUCCESS] scripts/tests/test-cilium-homogeneous-devices-flux-wait.sh
✅ [SUCCESS] scripts/tests/test-cilium-mutual-auth-policy-regressions.sh
✅ [SUCCESS] scripts/tests/test-cilium-mutual-auth-policy.sh
✅ [SUCCESS] scripts/tests/test-cilium-rollout-gate-suppression-signal.sh
✅ [SUCCESS] scripts/tests/test-crossplane-sync-exporter.sh
✅ [SUCCESS] scripts/tests/test-dr-rebuild-supersession-guard.sh
✅ [SUCCESS] scripts/tests/test-github-config-role-activation-parity.sh
✅ [SUCCESS] scripts/tests/test-kubescape-gate-frameworks-guard.sh
✅ [SUCCESS] scripts/tests/test-kyverno-admission-vpa.sh
✅ [SUCCESS] scripts/tests/test-megalinter-scan-counts-ignorefile.sh
✅ [SUCCESS] scripts/tests/test-normalize-sarif-paths.sh
✅ [SUCCESS] scripts/tests/test-openbao-oidc-role.sh
✅ [SUCCESS] scripts/tests/test-opencost-usage-scraper.sh
✅ [SUCCESS] scripts/tests/test-refresh-flux-ghcr-auth-safety.sh
✅ [SUCCESS] scripts/tests/test-restrict-tenant-secret-stores.sh
✅ [SUCCESS] scripts/tests/test-shared-publish-workflow-pin-guard.sh
✅ [SUCCESS] scripts/tests/test-summarize-sarif-findings.sh
✅ [SUCCESS] scripts/tests/test-verify-published-evidence.sh
✅ [SUCCESS] scripts/update-vendored-operators.sh
✅ [SUCCESS] scripts/validate-alert-coverage.sh
✅ [SUCCESS] scripts/verify-published-evidence.sh
✅ [SUCCESS] scripts/wait-for-platform-flux-revision.sh
⚠️ REPOSITORY / checkov - 9 errors
2026-08-10 14:57:41,436 [MainThread  ] [ERROR]  YAML error parsing k8s/bases/infrastructure/controllers/kubevirt/kubevirt-operator.yaml: expected a single document in the stream
  in "<unicode string>", line 2, column 1
but found another document
  in "<unicode string>", line 9, column 1
cloudformation scan results:

Passed checks: 0, Failed checks: 0, Skipped checks: 0, Parsing errors: 1

kubernetes scan results:

Passed checks: 1973, Failed checks: 9, Skipped checks: 32

Check: CKV_K8S_35: "Prefer using secrets as files over secrets as environment variables"
	FAILED for resource: Deployment.minio.minio
	File: /k8s/providers/docker/infrastructure/controllers/minio/deployment.yaml:12-104
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-33

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_35: "Prefer using secrets as files over secrets as environment variables"
	FAILED for resource: Job.minio.minio-create-bucket
	File: /k8s/providers/docker/infrastructure/controllers/minio/job.yaml:4-76
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-33

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_25: "Minimize the admission of containers with added capability"
	FAILED for resource: Deployment.kube-system.coredns
	File: /k8s/providers/docker/infrastructure/controllers/coredns/deployment.yaml:2-146
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-24

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_11: "CPU limits should be set"
	FAILED for resource: Deployment.kube-system.coredns
	File: /k8s/providers/docker/infrastructure/controllers/coredns/deployment.yaml:2-146
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-10

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_35: "Prefer using secrets as files over secrets as environment variables"
	FAILED for resource: CronJob.umami.umami-provision-tenants
	File: /k8s/bases/apps/umami/cron-job.yaml:44-318
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-33

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_22: "Use read-only filesystem for containers where possible"
	FAILED for resource: CronJob.umami.umami-provision-tenants
	File: /k8s/bases/apps/umami/cron-job.yaml:44-318
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-21

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_40: "Containers should run as a high UID to avoid host conflict"
	FAILED for resource: CronJob.openbao.vault-snapshot
	File: /k8s/bases/infrastructure/vault-backup/cron-job.yaml:23-197
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-37

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_40: "Containers should run as a high UID to avoid host conflict"
	FAILED for resource: Job.openbao.vault-snapshot-init
	File: /k8s/bases/infrastructure/vault-backup/job.yaml:23-191
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-37

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
Check: CKV_K8S_35: "Prefer using secrets as files over secrets as environment variables"
	FAILED for resource: CronJob.observability.cnpg-degraded-alert
	File: /k8s/bases/infrastructure/controllers/coroot/cron-job-cnpg-degraded-alert.yaml:56-204
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-33

		Code lines for this resource are too many. Please use IDE of your choice to review the file.
github_actions scan results:

Passed checks: 128, Failed checks: 0, Skipped checks: 0
⚠️ SPELL / cspell - 3213 errors
up",
        "entrys",
        "envsubst",
        "esac",
        "etcdctl",
        "evictable",
        "extensionless",
        "externalsecret",
        "externalsecrets",
        "fakerepo",
        "fanout",
        "featureflagsource",
        "fleetdm",
        "fluxinstance",
        "fromdateiso",
        "gatewayapi",
        "generatable",
        "generatingpolicies",
        "genkey",
        "gethomepage",
        "gitops",
        "gocritic's",
        "golangci",
        "gosec",
        "grjtvs",
        "growfs",
        "growpart",
        "healthchecks",
        "healthz",
        "helmrelease",
        "helmreleases",
        "helmv",
        "heredocs",
        "homelab",
        "hostnames",
        "httproute",
        "idempotently",
        "ignorefile",
        "imagetools",
        "imagevalidatingpolicy",
        "imranismail",
        "injective",
        "inspectable",
        "iscsi",
        "italicise",
        "ivpol",
        "jobif",
        "keylessly",
        "keypair",
        "kprobes",
        "kptr",
        "krew",
        "ksail",
        "ksail's",
        "ksailcd",
        "kubeconfig",
        "kubeconform",
        "kubeconform's",
        "kubelet",
        "kubelet's",
        "kubelets",
        "kubelogin",
        "kubescape",
        "kubescape's",
        "kubespan",
        "kubevirt",
        "kubevuln",
        "kustomization",
        "kustomizations",
        "kyverno",
        "letsencrypt",
        "libc",
        "libgnutls",
        "lintable",
        "livez",
        "loadtester",
        "locationless",
        "logfile",
        "luks",
        "lycheeignore",
        "machineconfig",
        "materialise",
        "materialised",
        "materialises",
        "maxage",
        "maxbackup",
        "maxsize",
        "maxx",
        "microtime",
        "misconfig",
        "misconfigs",
        "misordered",
        "mistargeted",
        "mitrelike",
        "mktemp",
        "mlock",
        "mutatingpolicies",
        "mutatingwebhookconfigurations",
        "myapp",
        "najsk",
        "neighbour",
        "nenv",
        "netlink",
        "netpol",
        "netpols",
        "neutralises",
        "neutralising",
        "nextjs",
        "nftables",
        "nilnil",
        "nobuckets",
        "nodepod",
        "nodeport",
        "nolint",
        "nonroot",
        "normalisation",
        "normalise",
        "normalised",
        "normalises",
        "normalising",
        "nosec",
        "nsalike",
        "nullglob",
        "ocirepository",
        "openbao",
        "opencost",
        "openfeature",
        "oras",
        "overclaimed",
        "overprovisioning",
        "parallelised",
        "partialgroup",
        "pasteable",
        "permissioning",
        "pipefail",
        "policyignore",
        "policyreports",
        "portforward",
        "preemptible",
        "preservingly",
        "prioritisable",
        "prioritisation",
        "prioritised",
        "privesc",
        "providerconfigs",
        "pseudonymization",
        "pseudonymized",
        "pseudonymizes",
        "publishapp",
        "publishprovider",
        "pushsecret",
        "pushsecrets",
        "pycache",
        "randomises",
        "rdqwpktr",
        "readyz",
        "reassertions",
        "recognisable",
        "recognisably",
        "recognise",
        "recognised",
        "recolour",
        "reconverges",
        "refreshfluxghcrauth",
        "regenerable",
        "releaserc",
        "rematerialise",
        "rematerialised",
        "replicaset",
        "repoint",
        "repointed",
        "repoints",
        "repositoryrulesets",
        "resizer",
        "restrictor",
        "retabbed",
        "retarget",
        "rmem",
        "rolebindings",
        "rollouts",
        "rshared",
        "sanitised",
        "sanitiser",
        "sanitising",
        "sarif",
        "scheckov",
        "schedulability",
        "schedulable",
        "scopeable",
        "scopeless",
        "seccomp",
        "secretbox",
        "secretstore",
        "seedable",
        "serialised",
        "serverside",
        "serviceaccount",
        "serviceaccounts",
        "sgdisk",
        "shellcheck",
        "shfmt",
        "shopt",
        "shortsha",
        "siderolabs",
        "siderolink",
        "sigstore",
        "skmde",
        "slurpfile",
        "sngle",
        "specnull",
        "spiffe",
        "srole",
        "startswith",
        "statefulset",
        "statemanager",
        "stdlib",
        "stepif",
        "storageclass",
        "subshell",
        "subtest",
        "summarised",
        "surfaceless",
        "syft",
        "syscall",
        "sysctls",
        "tagliteral",
        "tagonly",
        "talosconfig",
        "talosctl",
        "tanzu",
        "templatesyncignore",
        "thresholded",
        "tlsv",
        "tmpl",
        "tostring",
        "tracepoints",
        "trixie",
        "trueish",
        "trustd",
        "ture",
        "uids",
        "umami",
        "umami's",
        "unablated",
        "unclickable",
        "uncompilable",
        "uncordon",
        "uncordoned",
        "undecoded",
        "undercounts",
        "undispositioned",
        "unevidenced",
        "unexcepted",
        "unfiled",
        "ungated",
        "ungenerated",
        "unifi",
        "uninvoked",
        "unioned",
        "unmarshalling",
        "unmarshals",
        "unmodelled",
        "unparseable",
        "unprovisioned",
        "unrecognisable",
        "unrecognised",
        "unrepresentable",
        "unreviewed",
        "unroutable",
        "unrun",
        "unshippable",
        "unskipped",
        "untrackable",
        "unvalidated",
        "unwired",
        "upbound",
        "updatekeys",
        "upjet",
        "upstreaming",
        "urlencode",
        "userinfo",
        "userns",
        "ushfn",
        "validatable",
        "validatealertcoverage",
        "validatingwebhookconfigurations",
        "vcunav",
        "velero",
        "virt",
        "volumesnapshot",
        "vpas",
        "vulnerabilitymanifests",
        "vulnerabilitymanifestsummary",
        "vulns",
        "vxlan",
        "wffc",
        "wgpolicyk",
        "wildcarded",
        "wlid",
        "wmem",
        "workloadconfigurationscans",
        "workloadconfigurationscansummary",
        "worktrees",
        "yannh",
        "yubikey",
        "yzwvjjmcyfnl",
        "zizmor"
    ]
}


You can also copy-paste megalinter-reports/.cspell.json at the root of your repository

(Truncated to last 6666 characters out of 572788)
⚠️ COPYPASTE / jscpd - 185 errors
tokens)
   scripts/tests/refresh-flux-ghcr-auth/rollout_safety_test.go [468:57 - 485:5]
Clone found (go)
 - scripts/tests/refresh-flux-ghcr-auth/rollout_safety_test.go [492:77 - 508:11] (17 lines, 118 tokens)
   scripts/tests/refresh-flux-ghcr-auth/rollout_safety_test.go [519:110 - 535:11]
Clone found (bash)
 - scripts/tests/test-cilium-bandwidth-manager-component.sh [9:1 - 54:2] (46 lines, 202 tokens)
   scripts/tests/test-cilium-homogeneous-devices-activation.sh [9:1 - 54:2]
Clone found (bash)
 - scripts/tests/test-cilium-bandwidth-manager-component.sh [52:5 - 72:2] (21 lines, 67 tokens)
   scripts/tests/test-cilium-homogeneous-devices-activation.sh [80:23 - 100:2]
Clone found (bash)
 - scripts/tests/test-cilium-bandwidth-manager-component.sh [54:1 - 72:2] (19 lines, 65 tokens)
   scripts/tests/test-opencost-usage-scraper.sh [15:1 - 33:2]
Clone found (bash)
 - scripts/tests/test-cilium-mutual-auth-policy.sh [28:29 - 41:10] (14 lines, 78 tokens)
   scripts/tests/test-cilium-mutual-auth-policy.sh [79:33 - 92:10]
Clone found (bash)
 - scripts/tests/test-cilium-mutual-auth-policy.sh [98:33 - 107:54] (10 lines, 57 tokens)
   scripts/tests/test-cilium-mutual-auth-policy.sh [118:32 - 127:54]
Clone found (bash)
 - scripts/tests/test-crossplane-sync-exporter.sh [56:3 - 118:11] (63 lines, 338 tokens)
   scripts/tests/test-opencost-usage-scraper.sh [22:45 - 84:11]
Clone found (bash)
 - scripts/tests/test-refresh-flux-ghcr-auth-safety.sh [177:5 - 185:51] (9 lines, 76 tokens)
   scripts/tests/test-refresh-flux-ghcr-auth-safety.sh [186:5 - 194:51]
Clone found (python)
 - scripts/tests/test_validate_homepage_bookmarks.py [46:57 - 54:54] (9 lines, 58 tokens)
   scripts/tests/test_validate_homepage_bookmarks.py [100:53 - 109:54]
Clone found (go)
 - scripts/validate-dr-signing/main_test.go [1007:13 - 1015:2] (9 lines, 51 tokens)
   scripts/validate-dr-signing/main_test.go [1075:12 - 1083:2]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [244:50 - 249:24] (6 lines, 103 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [756:31 - 761:24]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [276:14 - 282:4] (7 lines, 115 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [603:43 - 609:4]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [302:13 - 311:7] (10 lines, 158 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [828:18 - 837:7]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [311:1 - 316:8] (6 lines, 93 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [838:1 - 843:8]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [388:5 - 393:2] (6 lines, 82 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [574:8 - 579:9]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [389:1 - 399:23] (11 lines, 220 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [666:60 - 677:3]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [393:15 - 404:2] (12 lines, 185 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [494:17 - 505:2]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [440:15 - 451:12] (12 lines, 264 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [649:1 - 662:3]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [503:2 - 509:19] (7 lines, 89 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [688:7 - 694:19]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [503:2 - 509:33] (7 lines, 103 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [1013:58 - 1019:33]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [503:2 - 509:4] (7 lines, 74 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [1126:5 - 1132:4]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [596:30 - 601:8] (6 lines, 50 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [623:44 - 628:8]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [710:22 - 716:2] (7 lines, 135 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [1212:22 - 1218:2]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [951:33 - 959:11] (9 lines, 118 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [963:130 - 971:11]
Clone found (go)
 - scripts/validate-eks-ci-role-policy/main_test.go [1158:47 - 1163:2] (6 lines, 166 tokens)
   scripts/validate-eks-ci-role-policy/main_test.go [1238:46 - 1243:2]
Clone found (go)
 - scripts/validate-flux-verify/instance_test.go [109:62 - 126:31] (18 lines, 57 tokens)
   scripts/validate-flux-verify/instance_test.go [161:57 - 178:31]
Clone found (go)
 - scripts/validate-flux-verify/instance_test.go [109:62 - 128:35] (20 lines, 62 tokens)
   scripts/validate-flux-verify/instance_test.go [198:55 - 217:26]
Clone found (python)
 - scripts/validate-naming.py [126:52 - 132:25] (7 lines, 53 tokens)
   scripts/validate-naming.py [171:82 - 177:29]
┌────────┬────────────────┬─────────────┬──────────────┬──────────────┬──────────────────┬───────────────────┐
│ Format │ Files analyzed │ Total lines │ Total tokens │ Clones found │ Duplicated lines │ Duplicated tokens │
├────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ bash   │ 42             │ 12845       │ 48551        │ 20           │ 295 (2.30%)      │ 1797 (3.70%)      │
├────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ go     │ 36             │ 29911       │ 180577       │ 99           │ 804 (2.69%)      │ 7637 (4.23%)      │
├────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ python │ 4              │ 807         │ 5606         │ 2            │ 14 (1.73%)       │ 111 (1.98%)       │
├────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ txt    │ 57             │ 3378        │ 109125       │ 64           │ 2417 (71.55%)    │ 80219 (73.51%)    │
├────────┼────────────────┼─────────────┼──────────────┼──────────────┼──────────────────┼───────────────────┤
│ Total: │ 139            │ 46941       │ 343859       │ 185          │ 3530 (7.52%)     │ 89764 (26.10%)    │
└────────┴────────────────┴─────────────┴──────────────┴──────────────┴──────────────────┴───────────────────┘
Found 185 clones.
HTML report saved to megalinter-reports/copy-paste/jscpd-report.html
ERROR: jscpd found too many duplicates (7.5%) over threshold (0.0%)
time: 1.48s

(Truncated to last 6666 characters out of 39333)
⚠️ MARKDOWN / markdownlint - 64 errors
ength Line length [Expected: 400; Actual: 1784]
AGENTS.md:103:401 error MD013/line-length Line length [Expected: 400; Actual: 439]
AGENTS.md:105:401 error MD013/line-length Line length [Expected: 400; Actual: 1126]
AGENTS.md:106:401 error MD013/line-length Line length [Expected: 400; Actual: 628]
AGENTS.md:107:401 error MD013/line-length Line length [Expected: 400; Actual: 1774]
AGENTS.md:160:401 error MD013/line-length Line length [Expected: 400; Actual: 649]
AGENTS.md:162:401 error MD013/line-length Line length [Expected: 400; Actual: 971]
AGENTS.md:189:401 error MD013/line-length Line length [Expected: 400; Actual: 970]
AGENTS.md:211:401 error MD013/line-length Line length [Expected: 400; Actual: 1510]
AGENTS.md:279:401 error MD013/line-length Line length [Expected: 400; Actual: 1016]
AGENTS.md:280:401 error MD013/line-length Line length [Expected: 400; Actual: 491]
AGENTS.md:281:401 error MD013/line-length Line length [Expected: 400; Actual: 468]
AGENTS.md:287:401 error MD013/line-length Line length [Expected: 400; Actual: 532]
AGENTS.md:289:401 error MD013/line-length Line length [Expected: 400; Actual: 523]
AGENTS.md:292:401 error MD013/line-length Line length [Expected: 400; Actual: 613]
AGENTS.md:293:401 error MD013/line-length Line length [Expected: 400; Actual: 714]
AGENTS.md:297:401 error MD013/line-length Line length [Expected: 400; Actual: 502]
AGENTS.md:301:401 error MD013/line-length Line length [Expected: 400; Actual: 441]
AGENTS.md:306:401 error MD013/line-length Line length [Expected: 400; Actual: 427]
AGENTS.md:409:401 error MD013/line-length Line length [Expected: 400; Actual: 1139]
AGENTS.md:411:401 error MD013/line-length Line length [Expected: 400; Actual: 1240]
AGENTS.md:427:401 error MD013/line-length Line length [Expected: 400; Actual: 1137]
AGENTS.md:438:401 error MD013/line-length Line length [Expected: 400; Actual: 790]
AGENTS.md:443:401 error MD013/line-length Line length [Expected: 400; Actual: 515]
CLAUDE.md:1 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "@AGENTS.md"]
docs/dr/alerting.md:226:28 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/crypto-custody.md:22:389 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/crypto-custody.md:23:264 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/crypto-custody.md:27:35 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/crypto-custody.md:27:161 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/crypto-custody.md:27:239 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/crypto-custody.md:114 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Custody recommendations"]
docs/dr/crypto-custody.md:245 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "Custody recommendations"]
docs/dr/crypto-custody.md:251 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "What to do if it leaks"]
docs/dr/crypto-custody.md:258 error MD024/no-duplicate-heading Multiple headings with the same content [Context: "What to do if it is *lost* (no..."]
docs/dr/restore-drill.md:42 error MD028/no-blanks-blockquote Blank line inside blockquote
docs/dr/runbook.md:23:102 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/runbook.md:23:487 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/runbook.md:34 error MD028/no-blanks-blockquote Blank line inside blockquote
docs/dr/runbook.md:41 error MD028/no-blanks-blockquote Blank line inside blockquote
docs/dr/runbook.md:50 error MD028/no-blanks-blockquote Blank line inside blockquote
docs/dr/runbook.md:489:92 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/spire-server-ha.md:93 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/dr/velero-cnpg.md:11 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/dr/velero-cnpg.md:56:78 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/velero-cnpg.md:56:166 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/velero-cnpg.md:57:78 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/velero-cnpg.md:57:227 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/velero-cnpg.md:58:78 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/dr/velero-cnpg.md:58:166 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
docs/github-management.md:38:401 error MD013/line-length Line length [Expected: 400; Actual: 419]
docs/github-management.md:40:401 error MD013/line-length Line length [Expected: 400; Actual: 522]
docs/node-autoscaling.md:14 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/oidc-kubectl.md:95 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/runtime-security.md:114 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/rwx-storage.md:9 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/unifi-management.md:14 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
docs/unifi-management.md:62 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
README.md:116:401 error MD013/line-length Line length [Expected: 400; Actual: 540]
README.md:237:32 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:237:36 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]

(Truncated to last 6666 characters out of 7077)
⚠️ REPOSITORY / trivy - 1 error
rn-smoke/job.yaml (kubernetes)
======================================================================
Tests: 118 (SUCCESSES: 116, FAILURES: 2)
Failures: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 0, CRITICAL: 0)

KSV-0125 (MEDIUM): Container verify-round-trip in job userns-longhorn-smoke (namespace: userns-longhorn-smoke) uses an image from an untrusted registry.
════════════════════════════════════════
Ensure that all containers use images only from trusted registry domains.

See https://avd.aquasec.com/misconfig/ksv-0125
────────────────────────────────────────
 k8s/providers/hetzner/apps/userns-longhorn-smoke/job.yaml:102-157
────────────────────────────────────────
 102 ┌         - name: verify-round-trip
 103 │           image: docker.io/library/busybox:1.38.0@sha256:fd8d9aa63ba2f0982b5304e1ee8d3b90a210bc1ffb5314d980eb6962f1a9715d
 104 │           imagePullPolicy: IfNotPresent
 105 │           command:
 106 │             - /bin/sh
 107 │             - -ec
 108 │           args:
 109 │             - |
 110 └               set -eu
 ...   
────────────────────────────────────────


KSV-0125 (MEDIUM): Container write-sentinel in job userns-longhorn-smoke (namespace: userns-longhorn-smoke) uses an image from an untrusted registry.
════════════════════════════════════════
Ensure that all containers use images only from trusted registry domains.

See https://avd.aquasec.com/misconfig/ksv-0125
────────────────────────────────────────
 k8s/providers/hetzner/apps/userns-longhorn-smoke/job.yaml:54-100
────────────────────────────────────────
  54 ┌         - name: write-sentinel
  55 │           image: docker.io/library/busybox:1.38.0@sha256:fd8d9aa63ba2f0982b5304e1ee8d3b90a210bc1ffb5314d980eb6962f1a9715d
  56 │           imagePullPolicy: IfNotPresent
  57 │           command:
  58 │             - /bin/sh
  59 │             - -ec
  60 │           args:
  61 │             - |
  62 └               set -eu
  ..   
────────────────────────────────────────



k8s/providers/hetzner/infrastructure/controllers/longhorn/cron-job-stale-node-cleanup.yaml (kubernetes)
=======================================================================================================
Tests: 116 (SUCCESSES: 115, FAILURES: 1)
Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)

KSV-0125 (MEDIUM): Container cleanup in cronjob longhorn-stale-node-cleanup (namespace: longhorn-system) uses an image from an untrusted registry.
════════════════════════════════════════
Ensure that all containers use images only from trusted registry domains.

See https://avd.aquasec.com/misconfig/ksv-0125
────────────────────────────────────────
 k8s/providers/hetzner/infrastructure/controllers/longhorn/cron-job-stale-node-cleanup.yaml:73-112
────────────────────────────────────────
  73 ┌             - name: cleanup
  74 │               # NOT registry.k8s.io/kubectl: that image is distroless (kubectl
  75 │               # binary only, no /bin/sh), so the shell script below could never
  76 │               # start — every run since the CronJob shipped failed with
  77 │               # StartError exit 128 "stat /bin/sh: no such file or directory"
  78 │               # (observed live 2026-07-02). alpine/k8s ships kubectl + a POSIX
  79 │               # shell; the tag tracks the kubectl minor, matching the cluster.
  80 │               image: docker.io/alpine/k8s:1.36.2@sha256:44ef4942e171939b9c665a4a84beb80e2dcdb9a24330d4651cfdfd2e9deecc47
  81 └               securityContext:
  ..   
────────────────────────────────────────



k8s/providers/hetzner/infrastructure/coroot/cron-job-alert-autosuppressor.yaml (kubernetes)
===========================================================================================
Tests: 116 (SUCCESSES: 115, FAILURES: 1)
Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)

KSV-0125 (MEDIUM): Container autosuppressor in cronjob coroot-alert-autosuppressor (namespace: observability) uses an image from an untrusted registry.
════════════════════════════════════════
Ensure that all containers use images only from trusted registry domains.

See https://avd.aquasec.com/misconfig/ksv-0125
────────────────────────────────────────
 k8s/providers/hetzner/infrastructure/coroot/cron-job-alert-autosuppressor.yaml:93-116
────────────────────────────────────────
  93 ┌             - name: autosuppressor
  94 │               # curl + jq, digest-pinned (same image as custom-cloud-pricing).
  95 │               # observability is exempt from disallow-latest-tag.
  96 │               image: docker.io/badouralix/curl-jq:latest@sha256:1e7c0284e24572ace7170df9fc91f15fd3b79ebf056d4dde17244d5d74bbfabc
  97 │               securityContext:
  98 │                 allowPrivilegeEscalation: false
  99 │                 readOnlyRootFilesystem: true
 100 │                 runAsNonRoot: true
 101 └                 runAsUser: 65532
 ...   
────────────────────────────────────────



k8s/providers/hetzner/infrastructure/coroot/cron-job-custom-cloud-pricing.yaml (kubernetes)
===========================================================================================
Tests: 116 (SUCCESSES: 115, FAILURES: 1)
Failures: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)

KSV-0125 (MEDIUM): Container set-pricing in cronjob coroot-custom-cloud-pricing (namespace: observability) uses an image from an untrusted registry.
════════════════════════════════════════
Ensure that all containers use images only from trusted registry domains.

See https://avd.aquasec.com/misconfig/ksv-0125
────────────────────────────────────────
 k8s/providers/hetzner/infrastructure/coroot/cron-job-custom-cloud-pricing.yaml:77-114
────────────────────────────────────────
  77 ┌             - name: set-pricing
  78 │               # curl + jq, pinned by digest. jq replaces the former grep/sed/awk
  79 │               # JSON parsing + awk float compare with a robust, structure-tolerant
  80 │               # parse (the heartbeat CronJob still uses curlimages/curl — it has no
  81 │               # JSON to parse). No official curl+jq image exists, so this is the
  82 │               # de-facto community one, digest-pinned; observability is exempt from
  83 │               # disallow-latest-tag. Swappable for any curl+jq image.
  84 │               image: docker.io/badouralix/curl-jq:latest@sha256:1e7c0284e24572ace7170df9fc91f15fd3b79ebf056d4dde17244d5d74bbfabc
  85 └               securityContext:
  ..   
────────────────────────────────────────



📣 Notices:
  - Version 0.73.0 of Trivy is now available, current version is 0.71.2

To suppress version checks, run Trivy scans with the --skip-version-check flag

(Truncated to last 6666 characters out of 292319)

✅ Linters with no issues

actionlint, betterleaks, git_diff, golangci-lint, grype, jsonlint, lychee, osv-scanner, prettier, prettier, revive, secretlint, shellcheck, shfmt, syft, trivy-sbom, trufflehog, v8r, v8r, yamllint, zizmor

Notices

📣 MegaLinter 9.5.0 is out! Discover the new features and security recommendations in the release announcement. (Skip this info by defining SECURITY_SUGGESTIONS: false)

See detailed reports in MegaLinter artifacts

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

ci.yaml claimed the human-readable posture table reaches the log unchanged
under --format sarif. It does not: the Overall compliance-score line is absent,
measured on this PR's own CI run and reproduced locally. That made the
re-baselining instruction directly above it impossible to follow from the log.

The threshold is unaffected and still gates — ablated at 95/99/100 under
--format sarif for exit 0/1/1 against a combined score of 97.

Observability gap filed as #3058.
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@devantler I will review the changes in #3057.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Exercised as a user, and what the evidence actually shows

Ran the real command, both arms. Not the change traced through code — the exact CI invocation,
locally and then on this PR's own CI run.

Does the gate still gate? This was the one that mattered: with --format sarif the scan prints
no score, so a silent pass would be invisible. Ablated the threshold under that exact format:

--compliance-threshold exit
95 0
99 1
100 1

against a combined score of 97. It gates. (The same ablation under --format json gives the same
exits and does print 97, which is how I know the score itself is unchanged and only its display is
missing — now written into the step comment, and filed as #3058.)

Does MITRE actually get evaluated on the runner, not just on my laptop? Yes, and the CI log
proves it without needing the score: the posture table lists List Kubernetes secrets at 2
resources and Roles with delete capabilities at 4 — C-0015 and C-0007, both MITRE-only
controls, at exactly the counts I measured locally. Cross-environment agreement on the findings
themselves, which is stronger than agreement on an aggregate.

Do the exceptions still apply? wrote 21 exception policies then [success] Loaded exceptions
in the same CI run, and the score is 97 rather than the ~86 an unexcepted MITRE scan produces.

20/20 checks green at 71672ba4.

One thing I deliberately did NOT change

The SARIF upload still uses category: kubescape-nsa, which is now a slight misnomer since MITRE
findings ship under it too. Renaming a Code Scanning category closes every existing alert in the old
category and reopens them in the new one, which is real churn for a cosmetic label — and it is not
what this PR is about. Flagging it rather than silently leaving it: worth doing deliberately, on its
own, if you want it.

Scope I stopped at

52 of the 76 excepted controls are in neither framework and remain invisible to the gate. That is
recorded on #2823 with the per-control ablation behind it, not fixed here.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Kubescape validation now scans the NSA-CISA and MITRE ATT&CK frameworks. The 95 threshold applies to the combined score. Both validation workflows enforce matching framework coverage. SARIF output and exception generation remain enabled. New tests cover parsing, invalid configurations, decoy commands, missing scans, duplicate scans, workflow parity, and CI wiring. Documentation records coverage and exception behavior.

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title describes a security CI posture-gate evaluation, but it does not identify the main change to add MITRE framework coverage.
Description check ✅ Passed The description clearly explains the framework expansion, score threshold, newly visible findings, and remaining control coverage gaps.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @.github/workflows/ci.yaml:
- Around line 603-640: Add an executable offline regression test near the
Kubescape workflow step that uses the pinned KSAIL_VERSION and invokes the same
`ksail workload scan` configuration with both `nsa,mitre` frameworks. Provide
fixture findings covering a MITRE-only case, then assert combined framework
coverage and the threshold exit-code matrix: 95 succeeds while 99 and 100 fail.
Replace the comment-only ablation claim with this runnable check while
preserving the production SARIF scan gate.

In `@AGENTS.md`:
- Line 103: Correct the NSA coverage statement in the scan description:
distinguish the 20 controls evaluated by NSA from the 17 controls named by
ClusterSecurityException resources, or state only the accurate exception-control
count of 17. Keep the existing total-control and framework coverage context
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bd19688e-654b-40da-bc2d-dce7c1856047

📥 Commits

Reviewing files that changed from the base of the PR and between 68fe3fb and 71672ba.

📒 Files selected for processing (2)
  • .github/workflows/ci.yaml
  • AGENTS.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
.github/workflows/*.yaml

📄 CodeRabbit inference engine (AGENTS.md)

CI for Kubernetes-related changes must perform static KSail validation and Kubescape scanning; do not rely on full-cluster system tests.

Files:

  • .github/workflows/ci.yaml
🧠 Learnings (2)
📚 Learning: 2026-07-28T00:33:10.828Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2825
File: .github/workflows/dr-rebuild.yaml:70-73
Timestamp: 2026-07-28T00:33:10.828Z
Learning: For GitHub Actions concurrency configuration in this repo, don’t use `queue: single` on a shared production concurrency group (e.g., `prod-deploy`) that is used for normal production deployments—`queue: single` will cancel/replace any pending run in that group. Normal production deployments must use a uniform `queue: max` for that shared group to ensure serialization without coalescing. If you need DR rebuild coalescing (replacement of pending DR rebuild runs), it must use a separate DR-only concurrency scope/group (not the shared production `prod-deploy` group).

Applied to files:

  • .github/workflows/ci.yaml
📚 Learning: 2026-07-29T07:29:34.804Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2848
File: scripts/validate-publication-order/main.go:315-353
Timestamp: 2026-07-29T07:29:34.804Z
Learning: When reviewing GitHub Actions workflow steps with `run:` blocks, remember that the default non-interactive Bash invocation won’t expand shell aliases unless the script explicitly enables it (e.g., `shopt -s expand_aliases`). Therefore, when assessing potential command-name shadowing (e.g., whether an alias could change what command runs), only treat alias-based behavior as possible if the step explicitly opts into alias expansion via `shopt -s expand_aliases` (or equivalent).

Applied to files:

  • .github/workflows/ci.yaml
🪛 LanguageTool
AGENTS.md

[uncategorized] ~101-~101: The official name of this software platform is spelled with a capital “H”.
Context: ...thoritative list is the k8s filter in .github/workflows/ci.yaml) — the validate jo...

(GITHUB)


[uncategorized] ~101-~101: The official name of this software platform is spelled with a capital “H”.
Context: ...flows/ci.yaml) — the validatejob in.github/workflows/ci.yaml` first json-parses ev...

(GITHUB)


[uncategorized] ~105-~105: The official name of this software platform is spelled with a capital “H”.
Context: ...wire (kept in sync with the comments in .github/workflows/ci.yaml): if validate outp...

(GITHUB)


[style] ~106-~106: ‘whether or not’ might be wordy. Consider a shorter alternative.
Context: ...tside both frameworks is inert here whether or not it is correct, so never read "the score...

(EN_WORDINESS_PREMIUM_WHETHER_OR_NOT)

🔇 Additional comments (2)
.github/workflows/ci.yaml (1)

570-586: LGTM!

AGENTS.md (1)

101-102: LGTM!

Also applies to: 104-107

Comment thread .github/workflows/ci.yaml
Comment thread AGENTS.md Outdated
devantler and others added 2 commits August 10, 2026 15:00
Dropping a framework from the Kubescape gate REMOVES findings, so the compliance
score rises and every check stays green. That is a coverage regression shaped
like an improvement, and it is what left 59 excepted controls un-gated.

Add a guard asserting the scan still names every required framework, with a
fail-closed floor so renaming the step cannot make it pass vacuously, plus 11
RED-proved assertions and CI wiring for both halves.

Also corrects AGENTS.md line 103, which stated NSA's total control count (20)
where it meant the excepted-control subset (17).

Part of #2823
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@devantler I will review the changes in #3057.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit is rate limited at this head (cr:no-gate@4a06974e6e9d300c20a6c7251adfa513b2d1cea6), so advancing to the next review lane.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a06974e6e

ℹ️ 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".

Comment thread scripts/guard-kubescape-gate-frameworks.sh Outdated
Comment thread .github/workflows/ci.yaml
Two review findings, both real.

validate-main.yaml still scanned nsa only while uploading under the same Code
Scanning category as the PR analysis. That category is the durable baseline PR
alerts are diffed against, so every MITRE finding would have failed to persist
as a main-branch alert — and a direct push to main, which bypasses the merge
queue, was ungated on MITRE entirely. Both workflows now scan nsa,mitre and the
guard checks both.

The guard also read raw YAML, so a stale comment naming both frameworks could
satisfy it while the real command used a variable. Comments are now excluded.

16 assertions, up from 11.

Part of #2823
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Findings fixed and threads resolved, so restarting the review loop at CodeRabbit per lane priority.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@devantler I will review the updated changes in #3057.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit is rate limited at this head (cr:no-gate@68010ef94d61eb4d330145a614f58da829065fac), so advancing to the next lane. Both of your previous findings are fixed and their threads resolved.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 68010ef94d

ℹ️ 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".

Comment thread scripts/guard-kubescape-gate-frameworks.sh Outdated
Comment thread .github/workflows/validate-main.yaml
Comment thread scripts/guard-kubescape-gate-frameworks.sh Outdated
Three review findings, two fixed here.

The guard checked only that each workflow contained the required members, so
nsa,mitre,pss in ci.yaml against an nsa,mitre baseline passed — and one of my own
tests asserted that as correct, encoding the bug. Both workflows must now carry
identical, normalised sets; ordering and repetition are ignored.

The guard also ran only on the PR path, so a direct push to main could reduce
that workflow's own scan with nothing checking it. validate-main.yaml now runs
the guard before it scans.

20 assertions, up from 16. The raw-YAML residual (an output-only command that
merely prints the invocation) is tracked separately rather than blacklisted.

Part of #2823
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

All findings fixed and threads resolved; restarting the review loop at CodeRabbit.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@devantler I will review the updated changes in #3057.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@scripts/guard-kubescape-gate-frameworks.sh`:
- Around line 169-177: Update scan_invocations in
scripts/guard-kubescape-gate-frameworks.sh (169-177) to accept only supported
run: lines whose first non-blank command token is the direct executable ksail
followed by workload scan, failing closed for echo or other wrapper commands.
Add the rejected echo decoy case in
scripts/tests/test-kubescape-gate-frameworks-guard.sh (109-116) and verify it is
not treated as a scan invocation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a31aeae3-8362-490b-9cc0-81c8e3ecec8a

📥 Commits

Reviewing files that changed from the base of the PR and between 71672ba and 873dab3.

📒 Files selected for processing (5)
  • .github/workflows/ci.yaml
  • .github/workflows/validate-main.yaml
  • AGENTS.md
  • scripts/guard-kubescape-gate-frameworks.sh
  • scripts/tests/test-kubescape-gate-frameworks-guard.sh
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
.github/workflows/*.yaml

📄 CodeRabbit inference engine (AGENTS.md)

.github/workflows/*.yaml: CI for Kubernetes-related changes must use static manifest validation and Kubescape scanning; there is no full-cluster system test.
Do not lower the Kubescape compliance floor to accommodate findings; add minimal, justified ClusterSecurityException resources when appropriate.

Files:

  • .github/workflows/validate-main.yaml
  • .github/workflows/ci.yaml
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Use Conventional Commit prefixes such as feat:, fix:, or chore: for commits and PR titles.
Keep changes small and focused, create PRs as drafts, and never push directly to main.

Files:

  • AGENTS.md
  • scripts/tests/test-kubescape-gate-frameworks-guard.sh
  • scripts/guard-kubescape-gate-frameworks.sh
🧠 Learnings (3)
📚 Learning: 2026-07-28T00:33:10.828Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2825
File: .github/workflows/dr-rebuild.yaml:70-73
Timestamp: 2026-07-28T00:33:10.828Z
Learning: For GitHub Actions concurrency configuration in this repo, don’t use `queue: single` on a shared production concurrency group (e.g., `prod-deploy`) that is used for normal production deployments—`queue: single` will cancel/replace any pending run in that group. Normal production deployments must use a uniform `queue: max` for that shared group to ensure serialization without coalescing. If you need DR rebuild coalescing (replacement of pending DR rebuild runs), it must use a separate DR-only concurrency scope/group (not the shared production `prod-deploy` group).

Applied to files:

  • .github/workflows/validate-main.yaml
  • .github/workflows/ci.yaml
📚 Learning: 2026-07-29T07:29:34.804Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 2848
File: scripts/validate-publication-order/main.go:315-353
Timestamp: 2026-07-29T07:29:34.804Z
Learning: When reviewing GitHub Actions workflow steps with `run:` blocks, remember that the default non-interactive Bash invocation won’t expand shell aliases unless the script explicitly enables it (e.g., `shopt -s expand_aliases`). Therefore, when assessing potential command-name shadowing (e.g., whether an alias could change what command runs), only treat alias-based behavior as possible if the step explicitly opts into alias expansion via `shopt -s expand_aliases` (or equivalent).

Applied to files:

  • .github/workflows/validate-main.yaml
  • .github/workflows/ci.yaml
📚 Learning: 2026-08-10T13:01:12.782Z
Learnt from: devantler
Repo: devantler-tech/platform PR: 3057
File: .github/workflows/ci.yaml:622-659
Timestamp: 2026-08-10T13:01:12.782Z
Learning: Repository shell tests and scripts must remain compatible with macOS Bash 3.2. Do not use Bash 4+ features such as `mapfile`; use portable constructs, such as a `while IFS= read -r` loop, instead.

Applied to files:

  • scripts/tests/test-kubescape-gate-frameworks-guard.sh
  • scripts/guard-kubescape-gate-frameworks.sh
🪛 ast-grep (0.45.0)
scripts/tests/test-kubescape-gate-frameworks-guard.sh

[warning] 53-53: set +e (or set +o errexit) disables the shell's errexit option, so the script keeps running after a command fails. This masks failures of security-critical operations (downloads, signature/checksum verification, permission changes, cleanup of secrets), letting the script proceed with a bad or insecure state. Leave errexit enabled (set -e / set -euo pipefail), or handle failures explicitly with if/|| and an explicit exit instead of globally turning off failure detection.
Context: set +e
Note: [CWE-754] Improper Check for Unusual or Exceptional Conditions.

(set-plus-e-error-masking-bash)


[warning] 138-138: set +e (or set +o errexit) disables the shell's errexit option, so the script keeps running after a command fails. This masks failures of security-critical operations (downloads, signature/checksum verification, permission changes, cleanup of secrets), letting the script proceed with a bad or insecure state. Leave errexit enabled (set -e / set -euo pipefail), or handle failures explicitly with if/|| and an explicit exit instead of globally turning off failure detection.
Context: set +e
Note: [CWE-754] Improper Check for Unusual or Exceptional Conditions.

(set-plus-e-error-masking-bash)

🔇 Additional comments (5)
scripts/guard-kubescape-gate-frameworks.sh (1)

1-158: LGTM!

Also applies to: 180-180

scripts/tests/test-kubescape-gate-frameworks-guard.sh (1)

1-108: LGTM!

Also applies to: 118-173

.github/workflows/ci.yaml (1)

61-68: LGTM!

Also applies to: 157-159, 468-475, 589-659

.github/workflows/validate-main.yaml (1)

175-200: LGTM!

AGENTS.md (1)

101-107: LGTM!

Comment thread scripts/guard-kubescape-gate-frameworks.sh Outdated
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CI is fully green at this head and all twelve review threads are resolved — including the three P2s from the last Codex round, each fixed with a paired RED/GREEN arm rather than reasoning. A new head opens a new round, so restarting the loop at CodeRabbit per lane priority.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@devantler I will review the updated changes in #3057.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit is rate limited at this head (cr:no-gate@64411b578a3032faee69c340b5e5782c8713f984), so advancing to the next lane. CI is fully green here and all twelve threads are resolved.

Your three P2s from the previous head are fixed, each with a paired arm rather than an argument: the punctuated-suffix sets now reject (pre-fix they were accepted), two scan invocations now reject (pre-fix rc 0), and the wiring assertions read parsed run: scalars with a negative fixture proving a comment no longer satisfies them. The heredoc-body case stays open and scoped on #3060 — I am not claiming it here.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 64411b578a

ℹ️ 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".

Comment thread scripts/guard-kubescape-gate-frameworks.sh
The greedy --framework read judged the line on the throwaway scan. Codex, #3057.
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CI is green at this head and all thirteen threads are resolved. Codex's fourth P2 — a greedy --framework read judging a chained line on the throwaway scan — is fixed with a paired RED/GREEN arm. Restarting the loop at CodeRabbit per lane priority.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== Changed files ==='
git diff --name-status "$(git merge-base HEAD origin/main)" HEAD 2>/dev/null || \
  git diff --name-status HEAD~1 HEAD

echo '=== Diff stat ==='
git diff --stat "$(git merge-base HEAD origin/main)" HEAD 2>/dev/null || \
  git diff --stat HEAD~1 HEAD

echo '=== Bash script outlines ==='
ast-grep outline scripts/guard-kubescape-gate-frameworks.sh --items all 2>/dev/null || true
ast-grep outline scripts/tests/test-kubescape-gate-frameworks-guard.sh --items all 2>/dev/null || true

echo '=== Guard script ==='
cat -n scripts/guard-kubescape-gate-frameworks.sh

echo '=== Guard tests ==='
cat -n scripts/tests/test-kubescape-gate-frameworks-guard.sh

echo '=== Kubescape references in workflows ==='
rg -n -C 12 --glob '*.yaml' --glob '*.yml' '(kubescape|guard-kubescape-gate-frameworks|--framework|compliance-threshold)' .github/workflows

Length of output: 73754


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="$(git merge-base HEAD origin/main 2>/dev/null || git rev-parse HEAD~1)"

echo '=== Changed file modes ==='
git diff --summary "$base" HEAD
git ls-tree HEAD scripts/guard-kubescape-gate-frameworks.sh \
  scripts/tests/test-kubescape-gate-frameworks-guard.sh

echo '=== Changed hunks: guard and tests ==='
git diff --unified=35 "$base" HEAD -- \
  scripts/guard-kubescape-gate-frameworks.sh \
  scripts/tests/test-kubescape-gate-frameworks-guard.sh \
  AGENTS.md

echo '=== Repeated and malformed --framework fixture coverage ==='
rg -n -C 2 --glob '*.sh' \
  '(--framework[^[:space:]].*--framework|nsa,,mitre|nsa,mitre,|,--framework|framework_tokens|framework_argument)' \
  scripts

echo '=== Workflow parse and invocation context ==='
sed -n '45,75p;450,480p;585,665p' .github/workflows/ci.yaml
sed -n '165,205p' .github/workflows/validate-main.yaml

Length of output: 66835


@devantler No actionable findings. I verified the executable modes, guard wiring, equal nsa,mitre scan sets, and the new chained-scan rejection path. The test suite covers the reviewed fail-open cases.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Exercised at this head, and what the evidence shows

Ran the real guard against the real workflows, not the change traced through code. scripts/guard-kubescape-gate-frameworks.sh passes against the committed ci.yaml and validate-main.yaml, and the suite's own wiring arm asserts that.

Every fix has a paired arm measured on this branch, because a guard that only ever passes proves nothing:

Behaviour Pre-fix Post-fix
Framework sets differing only by a punctuated suffix (cis-v1.23-t1.0.1 vs cis-v1.24-t1.0.0) accepted (both truncated to cis) rejected
Two scan invocations in one workflow accepted (unioned) rejected
Two scan commands chained on one line accepted (greedy read took the throwaway) rejected
A --framework "$VAR" list read as a truncated prefix fails closed
Guard path present only in a comment / step name satisfied the wiring check no longer satisfies it

Directly measured the greedy read rather than inferring it: on --framework nsa,mitre,pss … && … --framework nsa,mitre, the old expression returned nsa,mitre — the scan whose SARIF nobody uploads.

30 assertions (from 24), shellcheck clean on both scripts, executable bits intact, CI green.

Scoped honestly

This closes the command-shape and YAML-context classes. A comment inside a run: block still matches, and a heredoc body beginning ksail still matches — that is the shell-context class, still open and correctly scoped on #3060. I am not claiming it here.

One defect found while building the wiring check, worth recording because it fails in the dangerous direction: yq … | grep -q under pipefail exits 141 (SIGPIPE), so the assertion reports "the guard is not wired" on a repository where it is — and the natural response to that false alarm is to delete the assertion. Values are captured before matching.

@devantler
devantler marked this pull request as ready for review August 10, 2026 15:08
@devantler
devantler added this pull request to the merge queue Aug 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 10, 2026
@devantler
devantler added this pull request to the merge queue Aug 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 10, 2026
@devantler
devantler added this pull request to the merge queue Aug 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 10, 2026
@devantler
devantler added this pull request to the merge queue Aug 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 10, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit was asked first at this head (marker 5242049348, 15:01Z) and completed — head status reads Review completed at 15:05:09Z — but produced no gate-satisfying artifact: no review object at 984ca5ca81 (the newest three are empty containers at older commits), no summary comment naming this head, and a command reply whose verdict says only "No actionable findings" with no at <sha> clause. A verdict naming no sha is stale evidence, not a current-head green, so this is a completed-without-gate outcome rather than a finding to fix. Recording cr:no-gate@984ca5ca81 and advancing one lane, per the ordered provider loop.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 984ca5ca81

ℹ️ 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".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Green review secured at 984ca5ca810b05e1bf80542bfe18773282d3ae53 — pentad clear, merge parked on a named blocker.

Codex reviewed this head at 17:30:08Z (Reviewed commit: 984ca5ca81, matching headRefOid[0:10]), following the request at 17:27:14Z — Codex Review: Didn't find any major issues, and its comment surface carries no ## Review finding section, so no comment-form P2 is hiding behind the clean pass. Pentad at head: 33 checks green, 0 unresolved threads, 0 body findings (the earlier ones sit at 1da2132acb and are historical), mergeStateStatus: CLEAN.

CodeRabbit was asked first, per lane priority, and completed at this head without a gate-satisfying artifact — its verdict named no sha — so this advanced one lane rather than spending a second provider after a success.

Merge is blocked by platform#3065, re-verified live this run. prod-control-plane-2 is still cordoned and still holds the residual GHCR drain fence, and #3063's merge_group run at 16:08Z was evicted with residual GHCR bridge ownership raised by both the deploy and the heal job. Every platform merge fails closed identically until the fence is released, so queueing this would re-hit the same failure rather than reveal anything new. Clearing it needs a kubectl mutation this lane is hard-denied.

This PR merges as soon as the fence is cleared; nothing else is outstanding on it.

@devantler
devantler added this pull request to the merge queue Aug 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 10, 2026
@devantler
devantler added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit 58e4af1 Aug 10, 2026
33 checks passed
@devantler
devantler deleted the claude/kubescape-gate-framework-coverage-2823 branch August 10, 2026 22:17
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

1 participant