Mastering Kubelet Security: Q&A on Kubernetes v1.36 Fine-Grained Authorization

By
<p>Kubernetes v1.36 makes a major stride in cluster security with the general availability (GA) of fine-grained kubelet API authorization. This feature, originally an alpha opt-in in v1.32 and beta-enabled by default in v1.33, now replaces the broad <code>nodes/proxy</code> permission with precise, least-privilege access controls. Below, we answer key questions about this enhancement, its motivation, and how it transforms kubelet access management.</p> <h2 id="what-is-fine-grained-kubelet-api-authorization">What exactly is fine-grained kubelet API authorization?</h2> <p>Fine-grained kubelet API authorization is a GA feature in Kubernetes v1.36 that lets you control access to the kubelet's HTTPS API on a per-endpoint basis. Instead of the old all-or-nothing <code>nodes/proxy</code> permission, you can now define separate RBAC rules for pods, metrics, logs, and exec operations. For example, a monitoring agent can be limited to reading <code>/metrics</code> and <code>/stats</code> without getting the ability to run commands inside containers. This is achieved by the <code>KubeletFineGrainedAuthz</code> feature gate, now locked to enabled, which maps each kubelet API path to a dedicated subresource (e.g., <code>nodes/metrics</code>, <code>nodes/log</code>, <code>nodes/exec</code>). This granularity allows administrators to apply the principle of least privilege precisely, reducing the blast radius of a potential compromise.</p><figure style="margin:20px 0"><img src="https://picsum.photos/seed/2947488238/800/450" alt="Mastering Kubelet Security: Q&amp;A on Kubernetes v1.36 Fine-Grained Authorization" style="width:100%;height:auto;border-radius:8px" loading="lazy"><figcaption style="font-size:12px;color:#666;margin-top:5px"></figcaption></figure> <h2 id="why-was-nodes-proxy-a-problem">Why was the old nodes/proxy permission so risky?</h2> <p>The <code>nodes/proxy</code> permission acted like a master key for the kubelet's API. Before v1.36, almost every kubelet endpoint—whether for reading pod logs, fetching node metrics, or executing commands—required this single permission. Granting it to monitoring agents, log collectors, or health checkers meant they could also execute arbitrary commands inside any container on the node. This violated the <strong>principle of least privilege</strong>. If an attacker compromised such a workload, they could pivot to run commands in every container, potentially exfiltrating data or installing malware. The community had flagged this issue for years (see <a href="https://github.com/kubernetes/kubernetes/issues/83465">kubernetes/kubernetes#83465</a>), and the new feature directly addresses that design flaw.</p> <h2 id="websocket-get-attack">How could a read-only permission like nodes/proxy GET lead to remote code execution?</h2> <p>Security researchers demonstrated in early 2026 that even the minimal <code>nodes/proxy GET</code> permission—commonly granted to monitoring tools—could be abused for remote code execution. The flaw lies in how WebSocket connections interact with the kubelet's RBAC model. The WebSocket protocol (RFC 6455) starts every connection with an HTTP GET request. The kubelet authorizes this GET using the <code>get</code> verb, but it does <strong>not</strong> perform a secondary check to see if the user also has <code>create</code> permission for the write operation that follows. Using a tool like <code>websocat</code>, an attacker could directly hit the kubelet's <code>/exec</code> endpoint on port 10250 and pass commands. For example: <br> <code>websocat --insecure --header "Authorization: Bearer $TOKEN" --protocol v4.channel.k8s.io "wss://$NODE_IP:10250/exec/default/nginx/nginx?command=sh"</code><br> This bypass effectively turned a read-only token into a full command execution capability.</p> <h2 id="what-new-rbac-resources-are-available">What new RBAC resources does fine-grained authorization introduce?</h2> <p>With fine-grained kubelet authorization, you now have separate subresources for each major kubelet API endpoint. These include:<br> <ul> <li><strong>nodes/metrics</strong> – for accessing node metrics (e.g., <code>/metrics</code>)</li> <li><strong>nodes/stats</strong> – for pod and container statistics (e.g., <code>/stats</code>)</li> <li><strong>nodes/log</strong> – for reading container logs (<code>/logs</code>)</li> <li><strong>nodes/exec</strong> – for executing commands in containers (<code>/exec</code>)</li> <li><strong>nodes/portforward</strong> – for port forwarding to pods (<code>/portForward</code>)</li> <li><strong>nodes/proxy</strong> – retained for backward compatibility with endpoints not yet subdivided</li> </ul> Administrators can create RBAC rules like <code>get nodes/metrics</code> for a monitoring agent, <code>get nodes/log</code> for a log collector, and only grant <code>create nodes/exec</code> to specific tools that require command execution. This eliminates the need to grant the overly broad <code>nodes/proxy</code> permission for common observability tasks.</p> <h2 id="how-to-migrate-from-nodes-proxy">How do I migrate from the old nodes/proxy permission?</h2> <p>Upgrade your cluster to <strong>Kubernetes v1.36</strong>, which has the feature gate locked to enabled. Then, audit your existing RBAC roles that use <code>nodes/proxy</code> and replace them with fine-grained permissions. For example, if a Prometheus server currently has <code>get nodes/proxy</code>, change its ClusterRole to include <code>get nodes/metrics</code> and <code>get nodes/stats</code>. For a Fluentd log collector, grant <code>get nodes/log</code>. If you have custom controllers that need exec access, limit them to <code>create nodes/exec</code>. Use the <code>kubectl auth can-i</code> command to test new permissions: <code>kubectl auth can-i get nodes/log --as system:serviceaccount:monitoring:log-collector</code>. Test thoroughly in a non-production environment first. Finally, remove the old <code>nodes/proxy</code> permission from all roles where it is no longer needed.</p> <h2 id="is-there-still-a-use-for-nodes-proxy">Is there still a use for the nodes/proxy permission after v1.36?</h2> <p>Yes, but it should be reserved for specific administrative tasks that require access to the full kubelet API or for endpoints that have not been subdivided into fine-grained subresources. For instance, the kubelet's <code>/pods</code> endpoint (listing all pods) and <code>/healthz</code> might still map to <code>nodes/proxy</code>. Additionally, if you have legacy workloads that rely on direct, unfiltered proxy access to the kubelet, you can continue to grant <code>nodes/proxy</code> but only to a minimal set of trusted components. In general, however, the principle is: <strong>grant the narrowest permission necessary</strong>. For most monitoring and logging tools, the new subresources are sufficient and safer. Consider revisiting any role that still uses <code>nodes/proxy</code> and split it into granular rules where possible to reduce security risk.</p> <h2 id="what-are-the-security-benefits-in-practice">What are the security benefits in practice?</h2> <p>Fine-grained authorization significantly limits the blast radius of a compromised workload. For example, if a monitoring agent with only <code>get nodes/metrics</code> is breached, an attacker can see node metrics but cannot read container logs, execute commands, or port-forward. Similarly, a log collector with <code>get nodes/log</code> cannot access metrics or exec. This containment is crucial for multi-tenant clusters where different teams may manage observability tools. Additionally, the feature closes the WebSocket attack vector described earlier, because <code>get nodes/metrics</code> does not allow write operations like <code>/exec</code>. By following least privilege, you reduce the attack surface and make your cluster more resilient to incidents. This enhancement also brings Kubernetes in line with modern security best practices for API access control.</p>

Related Articles