返回资讯中心
外部精选
云计算
#Kubernetes#可观测性#Blog

Extending Kubernetes policy enforcement to runtime security for AI workloads

Nirmata created Kyverno and donated it to the CNCF in 2020. Kyverno is now a graduated CNCF project and is widely used for enforcing and automating configuration security and best practices. However, admission control a…

CNCF BlogNirmata2026/10/15 · 11 天前26 分钟阅读

以下正文同步自 CNCF Blog,版权归原站所有,已转换为易读排版。

Nirmata created Kyverno and donated it to the CNCF in 2020. Kyverno is now a graduated CNCF project and is widely used for enforcing and automating configuration security and best practices. However, admission control answers one question: does this spec look right? It cannot answer the question that matters once the pod is running: is this workload doing what its spec says it should? With autonomous AI agents and non-deterministic LLM-enabled applications, that gap is where most of the interesting incidents live. A container with an innocuous-looking image pulls a second-stage payload after startup. A sidecar with network access nobody scoped tightly enough starts talking to a destination no one approved. A process no configuration policy anticipated executes, because the policy only ever described the container’s declared behavior, not its runtime one. One approach to addressing this gap is kernel-level runtime enforcement, which enables security decisions to be applied as workloads execute. Nirmata Runtime for Kyverno is an open source implementation of this approach, using eBPF and Linux Security Modules (LSM) to extend policy enforcement beyond Kubernetes admission control.

Below the workload, not beside it

The design premise is simple: any control that runs beside a workload — a sidecar, an agent, a userspace proxy — is something that the workload’s own compromise can see, stall, or step around. A control that runs below it, in the kernel, enforcing at the same instruction as the syscall it’s gating, isn’t in that position. The workload doesn’t get a vote. Concretely, Nirmata Runtime attaches BPF-LSM programs directly to bprm_check_security and file_open, and cgroup-scoped eBPF programs to the egress path, per pod. Five behaviors, all decided in-kernel, all synchronous with the operation they gate:

  • exec — deny process execution by resolved kernel path
  • open — deny file access by resolved kernel path
  • network — deny egress by destination
  • protocol — deny by the application protocol actually spoken on the wire, independent of destination port — a reverse shell dressed up as HTTPS on 443 doesn’t get a pass just because the port looks right
  • dns — observe and report on resolution, without blocking, because DNS denial has failure modes worse than the traffic it would stop A blocked exec returns -EPERM before the process runs. A blocked connection never completes. There’s no window between “decision” and “enforcement” for a compromised workload to race.

Reusing Kubernetes policy concepts for runtime enforcement

If you already write Kyverno policies for admission, you already know the policy language here: CEL. RuntimePolicy targets workloads the same way — podSelector/namespaceSelector — and expresses allow/deny logic per behavior, including expressions that pull live values from a ConfigMap or an HTTP source on a refresh interval. Admission and runtime become one continuous policy story instead of two unrelated tools with two unrelated syntaxes glued together with tribal knowledge about which one to check first. Every policy ships in monitor mode by default. You watch what it would deny — including a WouldDeny counterfactual signal — before you ever flip it to enforce. Nothing goes into blocking mode silently. Besides the language, Nirmata Runtime uses the same reporting APIs i.e., OpenReports and will add fine-grained exceptions similar to Kyverno for a seamless operator experience.

The same guarantee for AI agents in your cluster

A coding agent, an MCP server, an autonomous pipeline step — these are pods too, and the reasoning above applies to them without a special case. But agents raise a specific question that admission control was never built to answer: an agent’s behavior isn’t fully known during deployment time, because part of what it does is generated by a model at runtime. You can review the image. You can’t review the decision the agent hasn’t made yet. For AI workloads with dynamically determined behavior, kernel-level enforcement offers an additional layer of control that operates independently of application-level safeguards. This can complement existing approaches to securing AI agents, including network policies, admission controls, and application-level guardrails. If an agent’s runtime is compromised — a prompt injection, a supply-chain dependency, a tool call that goes somewhere it shouldn’t — the enforcement boundary can’t be argued with, reasoned around, or quietly disabled by the thing running inside it, because it isn’t running in that process at all. Concretely, with Nirmata Runtime you can, per agent workload:

  • Bound which model providers and endpoints it’s allowed to talk to — dns and network behaviors report or block resolution and egress outside an approved list, catching an agent that starts calling a provider nobody reviewed.
  • Restrict which binaries and MCP servers it can launch — exec allow-lists close off arbitrary tool invocation to exactly what the workload contract says the agent may run.
  • Detect the agent CLIs and SDKs already present in an image you didn’t build with agents in mind, and the model files and MCP configs a workload reads, before those become undeclared surfaces. Here’s what that looks like as one policy on an agent pod that should only ever reach an internal LLM gateway, and should never read the credentials sitting on its own filesystem:
apiVersion: runtime.nirmata.io/v1alpha1
kind: RuntimePolicy
metadata:
  name: agent-gateway-only
spec:
  mode: enforce
  podSelector:
    matchLabels:
      nirmata.io/agent: "true"
  behaviors:
  - network:
      allow:
        values:
        - llm-gateway.ai-platform.svc.cluster.local
        - kube-dns.kube-system.svc.cluster.local
      deny:
        values:
        - "*"
  - protocol:
      allow:
        values:
        - tls
        - dns
      deny:
        values:
        - "*"
  - open:
      deny:
        values:
        - "/root/.aws/credentials"
        - "/root/.kube/config"
        - "/root/.ssh/id_rsa"
        - "/var/run/secrets/kubernetes.io/serviceaccount/token"

network and protocol both carry the “*” sentinel, so a connection has to clear both: the gateway’s address over the wrong protocol is denied, and TLS to anywhere else is too. open doesn’t need the sentinel here — these four paths are exactly the ones a compromised agent would reach for to pivot into the cloud account, the cluster, or another host, and naming them is enough. (open needs a BPF-LSM-active node; network/protocol only need cgroup v2 and BPF.) If a prompt injection gets a tool call to run cat ~/.aws/credentials or talk to some other endpoint entirely, the kernel has already made the decision before the agent’s own process — or whatever compromised it — gets a chance to argue. This is enforced the same way as any other workload — no agent-specific proxy, no separate control plane, no assumption that the agent’s own guardrails will hold. The worked examples are in examples/shadow-ai/, covering unexpected DNS, AI SDK detection, and MCP server/config discovery end to end.

Observability that says why, not just that

Runtime security monitoring benefits from contextual information that explains which policy triggered an enforcement decision, rather than reporting event counts alone. When Nirmata Runtime denies something, the kernel encodes the decision in the map key, and userspace re-evaluates the compiled policy against the observed target to attribute the exact policy responsible. If an event can’t be attributed, it isn’t dropped silently — it’s counted and logged as a gap (events_dropped_total{reason="unattributed_kernel_deny"}), because a monitoring blind spot that looks identical to “nothing happened” is worse than a visible error. Findings land as standard Kubernetes OpenReports objects — no proprietary dashboard required to see what your cluster is actually doing. Raw observation and a readable report are two different things, though, and CEL is what turns one into the other. Observing exec in monitor mode streams every process a pod runs — necessary, because you don’t know what you’re looking for yet, and useless as a report, because most of it is sh, grep, and the rest of a normal container’s argv. monitorFilter is a per-observation CEL predicate that runs before a finding is written, so the noise never reaches the Report at all:

apiVersion: runtime.nirmata.io/v1alpha1
kind: RuntimePolicy
metadata:
  name: detect-agent-cli
spec:
  mode: monitor
  podSelector:
    matchLabels:
      app: ai-workload
  behaviors:
  - exec:
      deny:
        values: ["*"]
  monitorFilter:
    expressions:
    - name: exec-events-only
      expression: 'has(event.exec)'
    - name: agent-cli-or-inference-server
      expression: >-
        event.exec.argv.exists(a, a in [
          "claude", "codex", "gemini", "aider", "goose", "opencode", "crush",
          "cursor-agent", "ollama", "litellm", "text-generation-launcher",
        ]) ||
        event.exec.argv.exists(a,
          a.startsWith("@anthropic-ai/") ||
          a.startsWith("@openai/") ||
          a.startsWith("@google/gemini-cli"))

The first expression is a guard — without it, the second one evaluates against open and network observations too, where event.exec doesn’t exist. The second is the actual question: not “did a binary run” but “was an agent CLI or a local inference server invoked,” matched on the name it was invoked under or the package a launcher fetched, because npx, uvx, and python are just interpreters — the identity is in argv, not in the exec path. One policy, no sidecar parsing logs after the fact, and a Report that already says an agent CLI showed up on a pod nobody built with agents in mind, not that a process ran.

What’s next

Runtime enforcement is one component of a broader, defense-in-depth approach to securing Kubernetes and AI workloads. Combining runtime controls with admission policies, network security, and application-level safeguards can help organizations address security risks across different stages of the workload lifecycle. Nirmata Runtime is available as an open source project. The community is invited to explore the implementation, review the examples, contribute improvements, and share feedback through the GitHub repository. like the project make sure you give it a ⭐ to show your support, and to receive updates.

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →