*Part 3 of An OS Where the AI Is Never a Principal.*
The previous post gave you the machinery: a tool is a capability, an agent is a vat, and underneath them sits a single axiom — an agent can only act on capabilities it holds. That axiom buys a real, structural property. The worst a hijacked agent can do is misuse the least authority you handed it. Never escalate. Never reach beyond the graph.
I spent the first two posts selling you on that. So I owe you the honest sequel: it is only half the job.
Here is the half I left out. An agent can bound the authority it holds and still ruin your week. Picture an agent with two perfectly legitimate capabilities — one to read your customer database, one to send a web request. Both were deliberately granted. Both are exactly the least authority each task needs. The agent reads the database, then sends it to an attacker. Trace the failure and look for the bug. It isn't the read cap; that was correct. It isn't the send cap; that was correct too. Neither capability is the bug.
The bug is the flow between them. And no amount of least-authority reasoning catches it, because every individual authority check passes.
Two axes, not one
Step back and ask what an untrusted agent can actually do to you. It turns out there are exactly two answers, and they are independent.
It can harm you by doing something — exercising authority. Deleting, sending, paying, spawning. This is the axis the whole confinement story so far has been about.
Or it can harm you by knowing something — holding information that then escapes. A secret it read, leaked onward through a channel it legitimately controls.
These do not reduce to each other. A least-authority agent with no limit on what flows out still leaks — it holds a legitimate outbound capability and a secret, and the database example above is exactly that case. A perfectly information-contained agent with too much authority still wreaks havoc — it cannot leak a thing, but it can *act*, and acting is plenty destructive. So you have to minimize both. Power and memory are the two axes along which an untrusted agent is dangerous, and an honest system shrinks both:
Minimize what an agent can *do*, and minimize what it *knows*. As little authority as the task needs, held as briefly as possible; as little information as the task needs, retained as briefly as possible.
Object-capabilities give you the first. Information-flow control gives you the second. You need both because the bug lives in the seam between them.
Why AI forces the second axis
The ocap tradition has always had the authority column. Dennis and Van Horn, KeyKOS, EROS, seL4, Mark Miller's E — fifty years of bounding what an actor can do. (If you want that machinery from the ground up, the companion Endo-and-Agoric series teaches it end to end.)
What it never urgently needed was the knowledge column, because the classic untrusted actor was a *program*. A program has structure. You can track that variable X is tainted and variable Y is not, and the taint propagates along well-defined edges. Confinement of information was a known idea — Lampson named it in 1973 — but it lived at the margins, because for ordinary code you could mostly reason about flows.
The language model breaks that. An LLM is a mixing function with a memory — the first actor that is simultaneously untrusted-to-behave *and* exposed-to-everything-it-reads. It blends its entire context into one latent state, and every output token is a function of the whole thing. The instant a secret enters the context, every subsequent token it emits is potentially a function of that secret. There is no sound per-token taint tracking through a giant mixing function. The thing that made classic IFC tractable — structure — is exactly what the model dissolves.
So AI doesn't *introduce* the knowledge axis. It *forces* it, by being the first untrusted actor that holds everything it has ever seen in one undifferentiated blob and emits from all of it at once.
The duals
Lay the two axes side by side and they line up as duals — same shape, opposite face.
| | Least authority | Least knowledge |
| --- | --- | --- |
| Governs | what the agent can *do* | what the agent can *know* |
| Mechanism | object-capabilities | information-flow + ephemerality |
| Question | *could it act?* | *should this data move?* |
| Worst case | misuse of least authority, never escalation | leak of information already near-worthless |
| Time-structure | revocable — enforce at the moment of action | irreversible — enforce at ingestion, then decay |
| Tradition | Dennis & Van Horn, KeyKOS, EROS, seL4, E | Lampson, Bell–LaPadula, forward secrecy |
Read the "Question" row out loud, because it is the whole post in two lines. Ocaps answer "could it act?" Information-flow answers "should this data move?" The first is about the forward authority graph: what can you reach and affect. The second is about the provenance graph: where did this data come from, and where is it allowed to go. A least-authority agent holding both caps from my opening example is fully ocap-correct and still leaks. That is not a flaw in ocaps. It is a question they were never built to ask.
Where the two checks meet
The elegant part — and the reason this isn't a bolt-on — is that both checks happen at the same place. The membrane around a vat already gates every outbound send on a single-threaded turn. Adding information-flow doesn't add architecture; it makes that one chokepoint check two predicates instead of one:
send passes ⟺ authority holds ∧ flow allowed
authority: does the agent hold this cap? // the ocap check, already there
flow: is the data's label ⊑ the sink's clearance? // the IFC check, newAuthority says "you may use the send cap." Flow says "...but not with *this* payload — it's tainted high." The same gate, doing dual duty. A send that satisfies one predicate and not the other is blocked. That is how the database leak finally gets caught: the read cap stamps the data secret, the outbound sink to evil.com has no clearance for secret, and the flow check fails even though every authority check passed.
Two labels: secrecy and taint
To make the flow check work, every datum carries a label, and the label has two directions — because the AI threats are themselves duals.
One direction is secrecy: high data must not flow out to a low sink. Your customer database must not reach a destination not cleared for it. That is injection-driven exfiltration — the leak.
The other is taint: low-trust data must not flow in to high-trust decisions. A web page the agent *read* must not silently *pull the trigger* on a security-sensitive action without a trusted check. This is the direction ocaps cannot give you at all. A least-authority agent can still be talked into misusing the authority it legitimately holds — and stopping the untrusted input from being the thing that fires the cap is precisely what the taint half buys.
Same lattice, run in opposite directions. Secrets can't flow down; taint can't flow up. I'm introducing these lightly here on purpose — the labels, the join rule, why you label the *turn* and not the token, and the move that makes confidentiality a race you win by expiry rather than a wall you defend forever, are the whole subject of the next post. For now the only thing to hold onto is that the second axis exists, it is mechanical, and it lives at the same membrane as the first.
The slogan
So here is the principle the two posts before this were circling, stated whole:
Aegis minimizes what an agent can do *and* what it knows. Object-capabilities bound its authority; information-flow and ephemerality bound its knowledge. The model is never a principal — only a subject, minimal in power and minimal in memory.
One honest caveat before I hand off. Least knowledge is not free. Every bit of context you withhold makes the model dumber — its usefulness *is* the context it can see. Push this too far and you get an agent that is perfectly secure and perfectly useless. So "least knowledge" means the least context that still clears the competence floor, not the least context, period. Treat knowledge as a budgeted resource exactly like authority: spend the minimum that keeps the model competent, and find that floor by measurement, not by slogan. It is a tension to manage, the exact dual of the old POLA-versus-usability tradeoff on the authority axis. The goal is an agent minimal in power and memory — not a lobotomized one.
That is the shape of the whole defense. Two axes, two minimizations, one membrane checking both. Next we get concrete about the labels.
End of Transmission.