Skip to content

fix(kubernetes): prevent CKV2_K8S_5 per-rule secrets bypass in ClusterRole - #7640

Open
SandwichProtector wants to merge 1 commit into
bridgecrewio:mainfrom
SandwichProtector:fix/ckv2-k8s-5-per-rule-secrets
Open

fix(kubernetes): prevent CKV2_K8S_5 per-rule secrets bypass in ClusterRole#7640
SandwichProtector wants to merge 1 commit into
bridgecrewio:mainfrom
SandwichProtector:fix/ckv2-k8s-5-per-rule-secrets

Conversation

@SandwichProtector

Copy link
Copy Markdown

Context

Fixes #7616

CKV2_K8S_5 is intended to fail when a ServiceAccount or Node is bound to a Role or ClusterRole that grants get, list, watch, or wildcard verbs on secrets without a resourceNames restriction.

The current YAML check treats rules.resourceNames exists as a role-wide safe condition. If a ClusterRole has one unrestricted secrets rule and a separate scoped rule with resourceNames, the presence of the second rule satisfies the flattened attribute check and the check incorrectly passes.

This is a common real-world operator pattern. Controllers often need resourceNames-scoped access to a pull secret plus broad create and manage access to secrets they generate dynamically. The broad rule cannot use resourceNames, so the combination creates a meaningful blind spot.

This is related to #7110 and #6765, same underlying per-rule correlation limitation.

Description

Replace the three separate attribute checks for resources, verbs, and resourceNames with a single JSONPath condition that looks for the risky pattern on the same RBAC rule entry.

The check now fails when any rule matches:

  • resources includes secrets or wildcard
  • verbs includes get, watch, list, or wildcard
  • resourceNames is absent

It passes only when no such unscoped rule exists, which correctly handles mixed rules where one rule is scoped and another is not.

Change is in checkov/kubernetes/checks/graph_checks/ReadAllSecrets.yaml.

Add test fixture MixedResourceNamesClusterRole.yaml with one unrestricted secrets rule plus one scoped rule, and update expected.yaml to expect failure for ClusterRoleBinding.default.mixed-secrets-global.

Steps to review

  • Verify check YAML at checkov/kubernetes/checks/graph_checks/ReadAllSecrets.yaml
  • Review new fixture tests/kubernetes/graph/checks/resources/ReadAllSecrets/Failing/MixedResourceNamesClusterRole.yaml
  • Run locally: pytest tests/kubernetes/graph/checks/test_yaml_policies.py -k ReadAllSecrets -o addopts='' -v
  • Run CLI smoke: checkov -f tests/kubernetes/graph/checks/resources/ReadAllSecrets/Failing/MixedResourceNamesClusterRole.yaml --framework kubernetes --check CKV2_K8S_5
  • Confirm existing passing fixtures still pass: RoleResourceName.yaml and Passing/ClusterRole.yaml

Checklist

New checks

  • No new checks, fix to existing CKV2_K8S_5

Real-world impact

An unrestricted secrets read bound to a ServiceAccount allows read of all secrets in namespace or cluster. When operators combine a scoped pull secret grant with a broad secret management grant in same ClusterRole, the old check missed it. This fix closes that false negative, improving RBAC least-privilege detection for operator workloads.

License

By submitting this pull request, I confirm that my contribution is made under the terms of Apache 2.0 license.

…rRole

The YAML check previously evaluated rules.resourceNames existence
across the entire Role, not per-rule. A ClusterRole with one
unrestricted secrets rule plus a scoped rule with resourceNames
incorrectly passed.

Replace three attribute checks with a single JSONPath that looks
for the risky case on the same rule entry: resources includes
secrets or wildcard, verbs includes get, watch, list or wildcard,
and resourceNames is absent. Check now passes only when no such
unscoped rule exists.

Add MixedResourceNamesClusterRole fixture and update expected
to require failure for mixed-secrets-global binding. Retains
existing passing fixtures for scoped resourceNames.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CKV2_K8S_5 passes when a ClusterRole/Role has one resourceNames-scoped secrets rule alongside a separate, unrestricted secrets rule

2 participants