Solo.io's agentshield Watches Your Agent Perimeter for Drift

Part of: Agent Security

Solo.io's agentshield builds an attack-path graph across Kubernetes, Istio, Cilium, AWS, and agentgateway, trusting a model only when it cites graph evidence.

I wrote about agent containment four days ago: default-deny egress, no ambient credentials, an audit log, one agentgateway config. All of that is a perimeter you build once. None of it tells you when the perimeter changes. A NetworkPolicy gets loosened for a deploy and never tightened back. A workload picks up a new ServiceAccount. A waypoint starts forwarding to a destination it never touched before. Nothing in a sandboxed-agent story watches for that, and on 2026-10-22 Solo.io shipped something that does: agentshield , open source under Apache-2.0, written up by Christian Posta on the Solo.io blog .

Defensive security research. This post analyses publicly disclosed findings so the controls that stop them can be tested. It describes mechanisms, not procedures, and links the primary sources for anyone verifying the work.

The pitch is narrow and the narrowness is the point: build one graph of what your workloads, identities, and policies actually are, flag the changes that look like a new path opening, and only ever propose a fix a person has to approve. I read through the source rather than just the announcement, because the part worth checking is exactly the part marketing copy tends to gloss: when does this thing actually call a model, and what does it trust the model to do unsupervised. Short answer: less than you’d guess, and the design is explicit about why.

One graph, five sources

agentshield discovers your environment into a single graph instead of asking four different tools four different questions:

  • Kubernetes: workloads, Pods, Services, ServiceAccounts, Nodes, RBAC, admission config, NetworkPolicies, Ingress, Gateway API, all through one shared informer per resource type.
  • Istio: AuthorizationPolicy, PeerAuthentication, ambient enrollment, waypoints, ServiceEntry, VirtualService.
  • Cilium: CiliumNetworkPolicy, CiliumClusterwideNetworkPolicy, CiliumEndpoint, CiliumNode.
  • agentgateway: the Gateway API resources agentgateway manages.
  • AWS: EC2 instances, ENIs, Security Groups, optionally CloudTrail change events through EventBridge and SQS.

Every fact in the graph records which plugin produced it, from which rule, from which observation, and the graph itself lives in Postgres as versioned, atomically replaced contributions with an ordered change feed. That provenance is not incidental. It’s what makes the next part trustworthy enough to let a model near it at all.

Traffic gets folded in too: Istio waypoint access logs over OTLP/HTTP, and AWS VPC Flow Logs through Firehose. Raw events land in JSONL or ClickHouse, and per-minute summaries become communicates-with edges in the graph. One gotcha worth knowing before you wire this up: Istio telemetry needs a custom envoyOtelAls extension provider that emits agentshield.* attributes, and the example configuration labels every caller as a Deployment, so traffic from other workload kinds gets rejected until you adjust it.

Detection runs with no model in the path

This is the design decision I went looking for, because it’s the one that decides whether this tool is trustworthy or just another AI product bolting a chatbot onto a dashboard. It isn’t. Built-in detectors look for new exposure, lost governance, a changed policy, new RBAC bindings, and workloads reaching destinations they never reached before, while explicitly ignoring rollouts and scaling so a routine deploy doesn’t page anyone. You can add your own CEL rules on top, with audited activation and hot reload. None of that calls a model. A match against an active rule, built-in or one you wrote, becomes a finding directly.

Here’s the shape of a real rule, confirmed against the project’s own test fixtures rather than just the blog copy:

Expression: "destination_ip_class == 'public' && destination_role == ''"

Read literally: a destination whose IP class is public and whose role is still unassigned. New traffic to a destination nobody has classified yet, flagged as medium risk under a reason tag of new_public_destination. destination_ip_class is itself documented in the detector’s own event schema as deliberately coarse: the field description says the raw address is never exposed, only its class. That’s a small design choice that says a lot about how the project thinks about what it logs.

Where the model actually shows up, and what it has to prove

Two flags turn on model calls, and both are off by default:

  • --agentic-investigation: a model looks at novelty signals (new paths, new exposure, lost governance) through six read-only MCP graph tools, and may promote a signal to a finding. It runs in its own sampled queue, so a slow or failing model call never delays detection itself.
  • --deployment-rule-authoring: a model drafts a detection rule for each Kubernetes Deployment, once per Pod template revision, after a baseline observation window. Drafted rules run in shadow mode until a person approves them.

The gate on both: a finding only gets accepted if the model cites facts and evidence the graph actually returned, including at least one medium-or-higher-risk signal, and the finding is invalidated the moment the underlying resources change out from under it. Run with neither flag enabled and you still get full discovery, the graph, its change history, telemetry ingestion, and the HTTP API and UI. You get no findings and no remediation proposals, because proposals are attached to findings and nothing is proposing anything without one.

The approval gate, not auto-remediation

Findings can suggest a Kubernetes NetworkPolicy, a CiliumNetworkPolicy, or an Istio STRICT PeerAuthentication. A person prepares the change (plans and dry-runs it against the live admission controller), approves it explicitly, and agentshield verifies the result afterward. Plugins declare which actions they support, and a blast-radius threshold controls what’s even allowed to run without that approval step. Nothing here closes a path on its own initiative. It tells you the path opened, shows its evidence, and hands you a specific, dry-run-checked fix to say yes to.

Trying it, and what I could and couldn’t verify

The README’s fastest path is a browser-only playground: make demo runs ui/pnpm install and starts a Vite dev server against a fake in-browser backend, no Go binary, no database, no cluster, no model required. Per the docs, you open http://127.0.0.1:5173, pick a scenario, trigger its observation, then prepare and approve the proposed remediation; reset puts the environment back. That’s a genuinely fast way to see the finding-to-approval flow without standing up Istio and Cilium first.

I did not run it in this session: executing a freshly cloned repository’s build and dev-server commands got blocked by this session’s own sandboxing, which is the right default for code that just arrived from the internet. What I did verify directly is the part a screenshot can’t prove: I cloned the repo, read the detector, event schema, and CEL compilation code in pkg/detector/, and confirmed the rule shape and field semantics above against the project’s actual Go source and test fixtures, not just its marketing page. If you want to see the playground itself, the commands above are copied verbatim from the project’s own README; run them yourself and tell me what scenario you got.

One more thing worth flagging before anyone points this at something real: the project’s own status note calls it pre-1.0, with breaking changes still expected in the API, database schema, and flags, and the web UI and HTTP API are unauthenticated and bound to loopback by default. That’s a reasonable default for a tool this new, and a reasonable default stops being safe the moment someone exposes it past their laptop. Review its documented security model before running agentshield anywhere outside a test environment.

Why this is the other half of containment

Agent containment answers whether the agent itself can get out. agentshield answers a different, ongoing question: did anything around the agent just open a path that wasn’t there yesterday, and what evidence proves it. A sandbox is a decision made once, at deploy time. A policy graph with a change feed checks that same decision on every subsequent change, and requires the model to cite graph evidence for every finding instead of asking you to trust its output. That combination, evidence-required detection plus a human approving every remediation, is a more disciplined design than either a model that flags everything or a person re-reading every NetworkPolicy by hand, and it’s worth watching whether agentshield keeps that discipline as it reaches 1.0.

Repo: github.com/agentshield-dev/agentshield . Docs: agent-shield.dev/docs .

Frequently asked questions

What is agentshield?

An open source (Apache-2.0) security tool Solo.io shipped on 2026-10-22, written up by Christian Posta. It builds one attack-path graph from Kubernetes, Istio ambient, Cilium, AWS, and agentgateway, runs detector rules against every change, and proposes NetworkPolicy, CiliumNetworkPolicy, or Istio PeerAuthentication fixes that a person must approve before anything is applied.

Does agentshield call a language model to detect every change?

No. Built-in CEL rules and any rule you activate match against every graph change with no model call at all. A model only runs if you turn on agentic investigation or deployment rule authoring, and even then a finding is accepted only if the model cites facts and evidence the graph actually returned, invalidated the moment those resources change.

What remediations can agentshield apply automatically?

None, by design. It proposes a Kubernetes NetworkPolicy, CiliumNetworkPolicy, or Istio STRICT PeerAuthentication change tied to a specific finding, but a person has to prepare it (plan and dry-run) and approve it before it touches the cluster. Plugins declare which actions they support, and a blast-radius threshold gates what could run without that approval.

Is agentshield production-ready?

Not yet. Its own README calls it an early, pre-1.0 project with breaking changes still expected in the API, database schema, and flags, and its web UI and API are unauthenticated and bound to loopback by default. Review its documented security model before running it anywhere outside a test environment.

Disagree or have a war story? Reply on X