BoundBench

kagent

Kubernetes-native framework/platform for running AI agents declaratively in clusters, with built-in k8s/Helm/Istio/Prometheus tools

github.com/kagent-dev/kagent · 2026-10-03 · 72a28f0

Defense-in-depth score

3.6 / 10

Minimal

kagent runs each agent in a gVisor-isolated Substrate actor whose network egress is limited to configured origins and whose model and MCP credentials are injected by an egress gateway rather than placed in the agent's environment - a genuinely strong isolation design. That design is undercut by the control plane it ships with: the default controller authentication mode is 'insecure' (any caller can claim any user, defaulting to admin) with a permit-all authorizer, and every agent actor is always allowed to reach that controller API, which can create agents, tool servers and model configs and call any registered MCP tool under a cluster-wide service account. Human approval of tool calls exists but is off by default, and there are no step, time or spend limits on the agent loop.

Key gaps (3)

  1. Default controller authentication accepts any caller-asserted user (default admin@kagent.dev) with a permit-all authorizer, and every agent actor is always allowed to reach that controller. C1 · Identity & least privilege
  2. The controller ServiceAccount holds cluster-wide create/update/patch/delete on all core, apps and batch resources, reachable through the unauthenticated API. C1 · Identity & least privilege
  3. Under the default insecure authentication any caller can assert the session owner's identity and answer a pending tool-approval request, so approval can come from a non-principal. C2 · Approval gates

Criteria

C1 Identity & least privilege

Minimal 0.15 / 1.00

Agent actors carry no Kubernetes service-account credentials of their own, and model/MCP keys are injected outside the actor, which is a good start. But every agent can always reach the kagent controller API, and by default that API trusts whatever user the caller claims (falling back to admin) and authorizes every action. Through it a caller can create or change agents, tool servers, model configs and call any registered MCP tool, all executed with the controller's cluster-wide service account that can create, update and delete every core, apps and batch resource. Least privilege therefore depends entirely on the operator switching to trusted-proxy mode and supplying a real authorizer.

C2 Approval gates

Minimal 0.25 / 1.00

kagent has a real human-in-the-loop mechanism: an MCP tool binding can set requireApproval, which pauses the task and shows the approver the exact tool name and arguments before resuming the same stored call. It is off by default, though, and it only covers MCP tool bindings - the skills bash tool, the Claude harness (run with --dangerously-skip-permissions) and the Codex harness (danger-full-access) are not gated, and the controller's CallMCPAppTool API can invoke any registered MCP tool directly without any approval. Kubernetes writes made through these tools are generally irreversible.

C3 Tool & action scoping

Minimal 0.45 / 1.00

Tool bindings can restrict an agent to a named subset of an MCP server's tools, and the built-in file tools resolve symlinks and require the result to stay inside the session or skills directory. The bash tool registered with skills is raw shell passthrough, and argument validation for the bundled Kubernetes tools lives in the separate kagent-tools server, which is not in this repository. An omitted tool list exposes every tool on the server.

C4 Code-execution isolation

Strong 0.72 / 1.00

Every agent runs as a Substrate actor whose sandbox class defaults to gVisor (microVM optional), there is no host-execution fallback, standalone sandboxes run the same way with no egress, and the actor's network egress is compiled into a DNS-origin allowlist. The concern is what sits inside that allowlist: the controller API endpoint is always added, and in the default insecure mode it lets code in the actor create agents and tool servers (kmcp MCPServer pods run outside Substrate) and call any MCP tool. Actors also keep a durable /data directory across restarts.

C5 Untrusted input blast radius

Minimal 0.05 / 1.00

Nothing in kagent tracks whether untrusted content (Kubernetes logs and objects, MCP tool results, sub-agent replies, A2A messages from other callers) has entered a session, and approval is not tied to it. The main structural limit is Substrate's egress allowlist, which prevents a hijacked agent from posting data to arbitrary internet hosts. A hijacked agent with Kubernetes tools bound can still make irreversible cluster changes without a human by default.

C6 Memory, context & configuration integrity

Minimal 0.30 / 1.00

Long-term memory is opt-in (pgvector disabled by default); when enabled, the model's save_memory tool writes arbitrary text that is preloaded into later sessions, and memory scoping is not enforced on every path. There are no auto-loaded workspace instruction files; skills are pinned to immutable commits. Agent system prompts and tool bindings live in AgentTemplates that the default unauthenticated API can rewrite, which would persist into every future session.

C7 Third-party extensions

Moderate 0.53 / 1.00

Code-bearing extensions are pinned: Harness images must be referenced by sha256 digest and skills by a full git commit or S3 object version, and the v1alpha3 compiler emits only HTTP/SSE MCP servers, not locally launched stdio servers. Remote MCP servers are not pinned, so their tool definitions can change between sessions without re-approval. Skill scripts run inside the agent's own actor with its full environment (which holds only credential placeholders).

C8 Secrets & sensitive-data protection

Moderate 0.50 / 1.00

Model API keys and Secret-backed MCP headers never enter the agent: the compiler replaces them with an inert placeholder and the Substrate egress gateway injects the real header only for the bound destination. Tool logging records only tool names and result keys, and OpenTelemetry export and message-content capture are off by default. There is no redaction of secrets returned by tools (for example Kubernetes Secret reads) before they reach the model or the stored history, the bundled Postgres ships fixed credentials, and credential binding through the control-plane API is not locked down.

C9 Audit & traceability

Minimal 0.45 / 1.00

Every task's messages and events are persisted by the controller into PostgreSQL through a TaskStore API, and the runtime stops if a save fails, so there is a durable conversation and tool-call history outside the agent. Runtime logs record each tool start and completion by name and call ID, though not arguments. Attribution is weak by default: the user identity is whatever the caller claims, and the runtime's TaskStore identity is an unsigned header the project itself labels insecure.

C10 Limits & kill switch

Minimal 0.15 / 1.00

The agent loop has no step, wall-clock or spend limit: no iteration cap exists in the Go ADK runtime and the controller's A2A client timeout defaults to none. Individual tools have timeouts (30-60 seconds for bash, 30 seconds for MCP servers) and tasks can be cancelled through A2A. Session idle expiry never applies to running tasks, so a runaway task is bounded only by the operator noticing and cancelling it.