Back to Checks
kubernetes

Role or ClusterRole does not grant get, list, or watch access to Kubernetes Secrets

rbac_minimize_secret_access
Service: rbacSeverity: high
OfficialBuilt-inVerified
Categories:identity-accesssecretscluster-security
Resource Type:ClusterRole

RBAC Roles and ClusterRoles granting read permissions to Kubernetes Secrets are identified. The evaluation looks for rules that allow get, list, or watch on secrets, either namespace-scoped or cluster-wide.

Prowler logoProwlerprowler-provider-kubernetes

Risk

Excessive Secret read access compromises confidentiality of tokens, keys, and credentials. Attackers can harvest service account tokens to impersonate workloads, pivot across namespaces, and modify resources, threatening integrity and availability via lateral movement.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler kubernetes --checks rbac_minimize_secret_access

Recommendation

Apply least privilege: avoid granting get, list, or watch on secrets except to narrowly scoped subjects. Constrain by namespace and resourceNames where feasible, use dedicated service accounts, avoid wildcards, and enforce separation of duties with policy and reviews.

Remediation

Terraform

# Remove secret read permissions by ensuring no rule includes the "secrets" resource
resource "kubernetes_cluster_role" "<example_resource_name>" {
  metadata {
    name = "<example_resource_name>"
  }
  rule {
    api_groups = [""]
    resources  = ["pods"] # Critical: do NOT include "secrets" to avoid get/list/watch on Secrets
    verbs      = ["get"]
  }
}

Other

1Identify the offending Role or ClusterRole name
2Edit it: run either `kubectl edit clusterrole <example_resource_name>` or `kubectl edit role <example_resource_name> <namespace>`
3In `rules`, remove any entry where `resources` contains `secrets` with verbs `get`, `list`, or `watch` (or delete those verbs/resources from the rule)
4Save and exit; the change applies immediately

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 = ["secret"]


class rbac_minimize_secret_access(Check):
    def execute(self) -> Check_Report_Kubernetes:
        findings = []
        # Check ClusterRoleBindings for seceret access
        for cr in rbac_client.cluster_roles.values():
            report = Check_Report_Kubernetes(
                metadata=self.metadata(), resource=cr.metadata
            )
            report.status = "PASS"
            report.status_extended = (
                f"ClusterRole {cr.metadata.name} does not have secret access."
            )
            if is_rule_allowing_permissions(cr.rules, resources, verbs):
                report.status = "FAIL"
                report.status_extended = (
                    f"ClusterRole {cr.metadata.name} has secret access."
                )
            findings.append(report)

        # Check RoleBindings for secret access
        for role in rbac_client.roles.values():
            report = Check_Report_Kubernetes(
                metadata=self.metadata(), resource=role.metadata
            )
            report.status = "PASS"
            report.status_extended = (
                f"Role {role.metadata.name} does not have secret access."
            )

            if is_rule_allowing_permissions(cr.rules, resources, verbs):
                report.status = "FAIL"
                report.status_extended = f"Role {role.metadata.name} has secret access."
            findings.append(report)

        return findings