BoundBench

mcp-server-kubernetes

TypeScript MCP server for kubectl/Helm management of Kubernetes clusters

github.com/Flux159/mcp-server-kubernetes · 2026-10-03 · 3d71add

Defense-in-depth score

2.6 / 10

Minimal

As shipped, this server gives the model the operator's full kubeconfig authority across every context, with exec into any pod, a generic kubectl tool, Helm installs from any repository, and forced deletes all enabled. It has a careful argv flag denylist and masks Secret values in kubectl_get, but the generic tool can run 'config view --raw', which returns raw credentials to the model, and neither the denylist nor the masking is a complete boundary. The dominant risk is a prompt-injected host agent using cluster-admin-equivalent credentials unattended; the read-only and allowlist modes that would contain it are opt-in.

Key gaps (3)

  1. Default local mode runs every tool with the operator's full kubeconfig across all contexts, with no authorization check. C1 · Identity & least privilege
  2. exec_in_pod and kubectl_generic run model-chosen commands in any pod, and arbitrary pods can be created, with no isolation from the server. C4 · Code-execution isolation
  3. Worst case under prompt injection from pod logs or resource fields: the default tool set can both exfiltrate cluster data and delete resources with no server-side human step. C5 · Untrusted input blast radius

Criteria

C1 Identity & least privilege

Minimal 0.00 / 1.00

In the default local mode the server loads the operator's own kubeconfig and runs every kubectl and helm command with it, and the model can pick any context in that file on every call, so it inherits the operator's full authority across every cluster they can reach. There is no server identity, no scoping of verbs or resources, and no authorization check of any kind before a command runs; the only narrowing is an opt-in tool allowlist set by environment variable. A hijacked or misled session therefore holds whatever the kubeconfig grants, which for most operators is cluster-admin.

C2 Approval gates

Minimal 0.33 / 1.00

As a tool server it relies on the host to ask the human, so what matters is how accurately it labels risk. Most mutating tools carry a destructive hint and there are dry-run options on apply, create, patch and node drain, but the labels are not reliable: some annotations are inaccurate, kubectl_create and port_forward carry no hints at all, and kubectl_generic mixes reads and writes in one tool. An opt-in read-only mode is enforced by the server on every call, though it is not a strict boundary. Deletes (including forced deletes and Helm uninstall) are irreversible with no preview.

C3 Tool & action scoping

Minimal 0.25 / 1.00

Every kubectl and helm invocation passes through one wrapper that rejects a denylist of dangerous flags (API server, token, impersonation, kubeconfig) and most tools refuse operands that start with a dash, which is a real improvement over raw passthrough. But kubectl_generic accepts any kubectl verb and any positional arguments, and the flag denylist is not a complete boundary. Helm tools accept any repository URL and chart, and every tool, including exec and generic kubectl, is enabled by default.

C4 Code-execution isolation

Minimal 0.00 / 1.00

exec_in_pod runs any model-chosen command inside any pod container in any namespace, and kubectl_apply, kubectl_create and kubectl_generic can create arbitrary pods, including privileged or host-mounted ones. The server provides no isolation around any of this: commands run inside existing workloads with their own service-account tokens and network access, and on the host side kubectl and helm run as the operator's user with the full environment. The argv is passed without a shell, which prevents shell injection on the host but is not a sandbox.

C5 Untrusted input blast radius

Minimal 0.07 / 1.00

Pod logs, events, exec output and resource fields are attacker-influenceable and are returned to the model as plain text with no provenance or untrusted marking. The default tool set gives a hijacked agent both exfiltration channels (a model-chosen Helm repository URL, creating pods that call out) and irreversible actions (forced deletes, Helm uninstall), with nothing in the server requiring a human. The opt-in read-only mode would remove most of the state-changing leg but is off by default.

C6 Memory, context & configuration integrity

Minimal 0.10 / 1.00

The server has no memory store, but the model can persistently rewrite the operator's kubeconfig, which the server and the operator's own kubectl load on every later run. kubectl_context's set operation switches the current context, and it is not the only kubeconfig-writing path. A single injected instruction can therefore leave behind a configuration that points future sessions, and the operator's own terminal, at a different cluster.

C7 Third-party extensions

N/A · full credit 1.00 / 1.00

The server loads no plugins, MCP servers or downloaded code into its own process: it only invokes the kubectl and helm binaries already installed by the operator. Helm charts installed from model-chosen repositories run in the cluster rather than in the server and are covered under tool scoping and untrusted-input blast radius.

C8 Secrets & sensitive-data protection

Minimal 0.25 / 1.00

Credentials come from the operator's kubeconfig or environment variables; inline kubeconfigs are written to a 0600 temp file. kubectl_get masks the values of Secret objects by default, but this is the only protected path: it can be turned off with MASK_SECRETS=false, it is not a complete boundary, and kubectl_generic can fetch Secrets or run 'config view --raw' to return the full kubeconfig, tokens and keys included, straight to the model. Telemetry is off by default and records only tool names and argument keys.

C9 Audit & traceability

Minimal 0.28 / 1.00

By default the server keeps no record of what it did: only kubectl_generic prints the command it runs to stderr, and nothing is written to a file the server owns. An opt-in OpenTelemetry integration wraps every tool call in a span, but it records only the tool name, argument names, context, namespace and resource type, not the commands or manifests, and it is off unless both ENABLE_TELEMETRY and an OTLP endpoint are set.

C10 Limits & kill switch

Minimal 0.33 / 1.00

Every kubectl and helm call has a default 1 MB output cap, and exec_in_pod, Helm and node operations have timeouts. But most kubectl calls (get, apply, delete, generic, logs with follow) have no timeout and run synchronously, the model can raise exec_in_pod and rollout timeouts itself, and there are no rate limits. Port-forward processes the server spawns are not stopped by cleanup or on shutdown.