A security model for agents that try to route around you
Most agent security assumes the agent will respect the layer that describes its rules. That is wrong. An agent can read the rule, reason about it, and try another route. It can change a path, call a wrapper, invoke an interpreter, or make a bypass sound ordinary.
The control has to live somewhere the agent cannot talk itself around.
Our security model uses two patterns for two boundaries. The first is a Backend for Frontend, or BFF, that protects the browser path into the cell management API. The second is content addressed kernel enforcement inside the agent cell, which protects the execution path once an agent is already running.
The BFF controls who can ask for fleet data and which credentials reach the backend. Kernel enforcement controls what a running cell can execute, load, write, and connect to.
The BFF protects the service boundary
The browser is not allowed to hold cell management credentials. It is not allowed to choose which backend token to send upstream. It is not allowed to ask for all cells and then filter locally.
The Console calls a BFF. The BFF authenticates the browser request with a bearer token and a tenant header. It resolves the tenant before it reads the request body. It then calls the real backend with a service credential that the browser never sees. The BFF translates the backend response into the smaller Console contract.
This is a boring pattern, and that is the point. The browser gets one stable API. The backend gets a service credential that never crosses into JavaScript. The internal cell API can change without exposing its shape to the client. Tenant filtering happens server side.
The backend may return cells for more than one tenant. The BFF filters the upstream response to the caller tenant before sending anything back to the Console. The client can still refuse to render a foreign tenant id, but that is only a second alarm. The server side BFF is the authority boundary.
Browser compromise does not reveal the cell management token. A client cannot widen its tenant scope by changing a query or a body. Internal topology and backend errors can be normalized before they reach the user interface.
The BFF is not meant to stop a process inside a cell from running node, copying wget, or opening a socket. Once an agent is inside the cell, the question changes from “may this user call this backend” to “may this process perform this operation”.
The cell boundary has to be below the harness
Ona’s Veto article made the right point: path based controls are brittle when the adversary can reason. They showed an agent bypassing a deny rule by changing the path to the same binary, then trying wrappers and a copied binary. Veto’s response is content addressed kernel enforcement. It identifies code by bytes rather than by the name used to reach it, and it enforces below the agent at kernel gates such as execve.
That diagnosis is correct. We use the same class of control, but it is wired into a broader governance model.
Our cells do not treat a kernel rule as a standalone deny list. The rule is derived from a mission manifest, a tenant, a cell id, an approval grant, and a tool policy. The result is not just “deny this binary”. The result is “this cell may execute these measured tools, load these measured libraries, write these paths, and connect only to these destinations”.
That is the main difference. Ona is right that identity by path is too weak. We add content identity to a larger system of tenant scope, approval, audit, and verification.
How content addressed enforcement works
The clean mental model is simple: a binary should not be judged by the string used to reach it. It should be judged by what it is.
The practical implementation is more careful. A BPF LSM program cannot hash megabytes of file content inside the kernel on every execution. The verifier forbids unbounded loops over file data, and execve is the wrong place to spend that latency. So the design does not depend on in kernel hashing.
Instead, trusted userspace measures the cell image at launch. The cell launcher reads a signed code catalog from the image, verifies the catalog against the image trust anchor, and binds allowed code identities to stable kernel objects such as device plus inode, or to kernel maintained measurements such as IMA or fs verity roots. The BPF LSM hook then performs a cheap map lookup at enforcement time.
The audit name is a digest, for example sha256:<hex>. The enforcement key is what the kernel can check quickly at the hook: the measured file identity, usually backed by a read only root filesystem, dm verity, fs verity, or IMA. High security profiles deny workspace created executables unless the build or test profile registers them.
The policy targets three gates.
The exec gate covers ordinary process execution. If a denied binary is reached as /usr/bin/node, /proc/self/root/usr/bin/node, a symlink, a hardlink, or a copied file in /tmp, the path is not the deciding fact. The measured content is.
The load gate covers file backed executable memory. If the dynamic linker is allowed, but it maps denied program text through mmap, the decision must happen at the executable mapping gate too. Otherwise execve is only one door among several.
The network gate covers the downstream effect. A downloader wants a socket. A package installer wants a registry. A data theft path wants egress. The launcher resolves named destinations in userspace, loads IP and CIDR sets into the policy, and lets the kernel enforce connection attempts.
Why the harness still matters
If the kernel is the boundary, it is tempting to treat the harness as irrelevant to security. That would be a mistake.
The harness is not the root of trust, but it is where intent is most precise. The cell launcher can apply a ceiling before the coding harness starts. Only the harness knows whether the next process is search, verification, git push, package install, or compilation.
Every tool spawn should route through a harness enforcement interface. The enforcer prepares a command, attaches a tool invocation id, applies a narrower child profile when possible, and records the result. The child profile can tighten Landlock and seccomp because both are monotonic. A child can narrow its permissions. It cannot widen past the outer policy already applied by the cell launcher.
This gives the model better feedback without making the model the guard. If a command fails because it tried to reach an unapproved destination, the harness can report that denial as a policy fact. If the denial is fatal, the cell result can say so with evidence.
The important rule is simple. Harness enforcement may tighten. It may explain. It may record. It may never be the only thing standing between the agent and the machine.
How we differ from Ona
Ona’s article is valuable because it names the right failure mode. The agent is goal directed, observant, and able to reason about controls. That changes the identity model for runtime security.
We agree with that. We differ in the scope of the control and in where the policy comes from.
Ona’s Veto, as described in the article, focuses on content addressed kernel enforcement for executables, starting at the execution gate, then expanding toward file, memory, and network primitives. Our platform starts from the mission cell as the unit of work. The policy is not a general host rule. It is a cell rule derived from the manifest and the grant that created the cell.
That gives us several advantages.
The policy is positive by default for high security cells. It is not only a deny list of known bad tools. The cell gets a catalog of known image code, known harness code, and known toolchain code. Unknown code does not get to run just because nobody named it yet.
The policy is tenant aware and cell aware. A denial is not just “node was blocked”. It is “cell X for tenant Y, under policy Z, attempted gate G, with digest D, while running tool invocation T”. That attribution matters when the output becomes a pull request, a deployment, or an audit bundle.
The policy composes with human approval. If a cell needs a capability beyond its ceiling, it asks the approval service for a narrow, time limited grant. The grant updates the runtime policy with an expiry enforced at the kernel gate. Approval is a signed change to runtime policy, not a prompt the agent can phrase its way through.
The policy is attached to verification. A cell result is accepted only after measured verification commands run in the same controlled workspace. The security record and the correctness record meet in the same result bundle.
The policy respects the isolation mode. A host guard can enforce container cells because they share the host kernel. It cannot see execve inside a microVM guest because the guest has its own kernel. MicroVM cells require enforcement inside the guest.
Where we are better
Ona’s content identity story is strong. Our claim is not that hashing a binary is novel. Our claim is that runtime content identity is more useful when it is tied to the rest of the agent system.
We are better for regulated work because the control is not isolated from governance. The BFF protects backend credentials. The approval service controls grants. The cell runtime launches the work. The coding harness tightens per tool. The event log records what happened. The artifact system receives the signed result. The audit trail can answer who authorized the action, what policy was active, what the kernel denied, and what verification ran.
We are better for sovereign deployments because the control runs where the customer runs the work, including disconnected networks. The model does not require a managed SaaS control plane to make sense.
We are better for agent factories because the unit of policy is the mission cell, not the developer workstation. A cell is born with a manifest, a budget, a repository scope, a tool policy, and an expiry. It dies after the work finishes. That lifecycle is the natural place to attach policy, revoke credentials, collect evidence, and preserve forensic artifacts.
We are also more explicit about the hard parts. BPF does not hash arbitrary file content in the hook. DNS names do not belong inside a kernel map. MicroVM execution cannot be enforced from the host kernel. JIT runtimes need a profile, not a blanket anonymous executable memory ban that quietly breaks Node.
What the diagrams hide
The clean diagram is useful, but the actual product has less tidy edges.
Full hardening needs kernel support. A cell that requests full enforcement must fail closed if BPF LSM, Landlock, seccomp, IMA, fs verity, or the trusted catalog anchor is missing. A silent downgrade is a vulnerability.
Temporary grants need active expiry. A BPF map entry does not delete itself because a human intended a five minute grant. The gate needs an expiry check in the kernel using monotonic time. Cleanup is housekeeping.
Catalog trust matters. A code catalog stored inside a mutable root filesystem is just another file the attacker can edit. The catalog has to be covered by a read only integrity anchor, or signed by a key outside the mutable image.
Workspace execution is tricky. Developers expect tests to run binaries they just built. Security teams do not want arbitrary newly compiled code to execute without review. The right answer is profile dependent.
The complete path
The Console calls the BFF. The BFF authenticates the user view, resolves the tenant, and injects the backend service credential. The cell runtime launches from a manifest. The approval service admits the requested capabilities. The cell launcher probes the kernel, validates the image catalog, compiles the policy, loads the guard, drops privilege, and starts the coding harness. The harness routes every tool through its enforcement interface. The kernel blocks operations outside policy. Denials become events. Verification runs in the controlled workspace. The result is signed, audited, and tied back to the mission.
That is the difference between a permission prompt and a security model.
A permission prompt asks the agent to cooperate. A BFF hides the service credential from the browser. Kernel enforcement removes the agent’s ability to route around the machine. The audit trail proves what happened. The verification gate proves the work is real.
Agents can reason. The security model has to assume they will.