User or group has no get, list, or watch permissions on the nodes/proxy sub-resource
RBAC permissions to the nodes/proxy subresource are analyzed. Any user or group granted get, list, or watch via cluster-wide bindings is reported.
Risk
Access to nodes/proxy exposes the Kubelet API through the apiserver proxy, which can bypass audit and admission controls. An adversary could execute commands in pods, read sensitive data, and pivot across nodes, impacting confidentiality and integrity; broad access also risks node-wide service disruption.
Run this check with Prowler
Run in Prowler Cloudprowler kubernetes --checks rbac_minimize_node_proxy_subresource_accessRecommendation
Apply least privilege: avoid granting any verbs on nodes/proxy to users or groups. If access is unavoidable, limit it to trusted admins, scope narrowly, make it time-bound, and enforce separation of duties. Prefer namespace roles over cluster-wide bindings and review RBAC regularly as part of defense in depth.
Remediation
CLI
kubectl delete clusterrolebinding <example_resource_name>Terraform
# Remove nodes/proxy access by defining the ClusterRole without that permission
resource "kubernetes_cluster_role" "<example_resource_name>" {
metadata {
name = "<example_resource_name>"
}
# Critical fix: no rule granting get/list/watch on "nodes/proxy" so subjects won't have that access
}Other
Check Code
from prowler.lib.check.models import Check, Check_Report_Kubernetes
from prowler.providers.kubernetes.services.rbac.lib.role_permissions import (
is_rule_allowing_permissions,
)
from prowler.providers.kubernetes.services.rbac.rbac_client import rbac_client
verbs = ["get", "list", "watch"]
resources = ["nodes/proxy"]
class rbac_minimize_node_proxy_subresource_access(Check):
def execute(self) -> Check_Report_Kubernetes:
findings = []
# Collect unique subjects and the ClusterRole names bound to them
subjects_bound_roles = {}
for crb in rbac_client.cluster_role_bindings.values():
for subject in crb.subjects:
# CIS benchmarks scope these checks to human identities only
if subject.kind in ["User", "Group"]:
key = (subject.kind, subject.name, subject.namespace)
if key not in subjects_bound_roles:
subjects_bound_roles[key] = (subject, set())
subjects_bound_roles[key][1].add(crb.roleRef.name)
cluster_roles_by_name = {
cr.metadata.name: cr for cr in rbac_client.cluster_roles.values()
}
for _, (subject, role_names) in subjects_bound_roles.items():
report = Check_Report_Kubernetes(metadata=self.metadata(), resource=subject)
report.resource_name = f"{subject.kind}:{subject.name}"
report.resource_id = f"{subject.kind}/{subject.name}"
report.status = "PASS"
report.status_extended = f"User or group '{subject.name}' does not have access to the node proxy sub-resource."
for role_name in role_names:
cr = cluster_roles_by_name.get(role_name)
if cr and is_rule_allowing_permissions(cr.rules, resources, verbs):
report.status = "FAIL"
report.status_extended = f"User or group '{subject.name}' has access to the node proxy sub-resource."
break
findings.append(report)
return findings