Skip to content

Enterprise deploymentCustomer-hosted or fully managed.Contact salesView pricing

Enforcing trust boundaries in a single token stream

Technical paper · September 10, 2026 · 8 min readBy Samuel OyanEngineer
architectureprompt injectionruntimeegress

A language model reads its system prompt, the user's query, and everything an agent retrieves as one undifferentiated sequence of tokens. There is no privilege separation inside that sequence. This paper argues the boundary must be reconstructed around the model — with provenance on the way in and egress control on the way out — and specifies the runtime checkpoints that do it.

Samuel OyanEngineer

Engineering notes on building a runtime AI-security gateway.

Technical paper · September 10, 2026 · 8 min read

Every serious LLM security failure of the last year — EchoLeak, the Slack AI and Copilot findings, the MCP tool-poisoning class — reduces to the same root cause: a language model processes its input as a single token sequence, and there is no reliable mechanism inside the model to enforce a privilege boundary between the system prompt, the user query, and content retrieved from the world. In conventional systems we separate trusted code from untrusted data with hardware and OS primitives. In an LLM, instruction and data are the same substance. Any span of text can be read as a command. This paper takes that constraint as given and asks the only useful question that follows: if the boundary cannot exist inside the model, where does it go?

The boundary is an architectural property, not a model property

Prompt engineering cannot fix this, and the field's own researchers have stopped pretending it can. Delimiters, “ignore anything that looks like an instruction,” and system-prompt hardening all operate inside the token stream, which is precisely the layer that has no privilege concept. They raise the cost of an attack marginally and provide no guarantee. The boundary that application security relies on — this input is untrusted, therefore it may not perform privileged actions — has to be reconstructed at a layer that can actually hold state about provenance and can actually stop an action. That layer is the runtime gateway the model's traffic passes through, not the model itself.

Control decisions outside the data plane
Preloopcontrol-plane foundationDashboard / APINext.js · Supabase RLSGovernance authoringpacks · OPA · policiescompile / pinDATA PLANEagentgatewayFly · v1.3.1Go enforcerExtAuthz · MCPCustomer appsitr_rt_* · /v1 · /mcp

The model and its context are the data plane. Trust decisions — what may enter, what an agent may do, what may leave — belong to a control plane the model cannot talk its way out of.

The injection kill chain
Ingestuntrusted contentInjecthidden instructionActagent tool callExfildata leavesBREAK ANY ONE LINK → ATTACK FAILSgateway checkpointgateway checkpointgateway checkpointgateway checkpoint

An exfiltration exploit needs four stages in sequence. A gateway checkpoint that breaks any single link defeats the whole chain — which is why the design places three independent, fail-closed checkpoints along it.

A scope-violation exploit like EchoLeak needs three things to succeed in sequence: untrusted content reaches the model's context, the model acts on an instruction embedded in that content, and the result leaves through a channel the attacker controls. Breaking any single link defeats the exploit. So we place three checkpoints, and we design each to be sufficient on its own, because defense that requires all layers to work is defense that fails when one does.

1. Ingress: classify and label provenance

Every span that enters the context gets a provenance label: system, user, or external — where external covers retrieval results, tool returns, MCP responses, and anything fetched from the network. External spans are classified for injection before the model is invoked. Classification here is not a keyword filter; it is the AI-first detection tier, which is why it lives at the gateway where it can run in the request path. The label is the important artifact: it travels with the content so that later checkpoints can enforce the rule that external text may not, by itself, authorize a privileged action.

Provenance travels with the span
CONTEXT SPANS, LABELED BY PROVENANCEsystemtrusted · authoritativeusertrusted · in-sessionexternal · untrustedRAG chunktool resultmay not authorize privileged actionspolicyEnforcementconstrain egress

System and user spans are trusted; external spans — RAG chunks, tool results — are labeled untrusted and carry a standing constraint: they may not, by themselves, authorize a privileged action. The label is what the action and egress checkpoints read.

2. Action: authorize at pre-action time

When the agent attempts a tool call, the call is evaluated before it executes — the resource, the arguments, the tenant, and the provenance of the instruction that motivated it. An action whose justification traces back to an external, unverified span is exactly the pattern to deny or escalate. This is pre-action authorization, and it is what converts “the model was convinced” into “the action was refused.” The model can be wrong; the permit is issued by something that cannot be prompt-injected because it does not read prompts.

3. Egress: inspect what leaves

The most-skipped checkpoint is the one EchoLeak abused. The model's output is inspected for data-shaped payloads smuggled into URLs, image references, and markup before the response is delivered or rendered. Sensitive context that is being encoded for exfiltration is blocked or redacted at this boundary. Egress control is what makes the first two checkpoints matter: even if injection slips through ingress and an action slips through authorization, the stolen data still has to walk out, and this is where it is stopped.

Fail closed at every checkpoint
RequestExtAuthzgRPC checkallowdeny / errorForward to LLM / MCP403 · no upstream call

Each checkpoint is enforced through external authorization that denies on timeout or uncertainty. A boundary that opens when the guard is unavailable is not a boundary.

Fail-closed, or it is theater

A checkpoint that passes traffic when it is overloaded, uncertain, or unavailable provides the illusion of a boundary and none of the substance. Each of the three checkpoints is enforced through external authorization that returns deny by default: if the classifier times out, if provenance is missing, if the permit service cannot be reached, the request does not proceed. This is the single most common place where LLM security designs quietly fail — the guard is real but fail-open, so any pressure that degrades it also disables it. We treat deny-on-uncertainty as non-negotiable, and we accept the availability cost that comes with it.

The latency constraint is what makes it a design problem

None of this is interesting if it adds a second of latency to every turn; operators will route around it. The engineering problem is doing ingress classification, pre-action authorization, and egress inspection inside a tight budget on the hot path. That forces a tiered design: cheap deterministic checks reject the obvious cases immediately, and the expensive AI-first classification is reserved for the spans that survive the cheap tier. The boundary is only useful if it is fast enough to leave on.

What this does and does not claim

This architecture does not solve prompt injection; nothing does, and claiming otherwise is how you ship a false badge. What it does is relocate the trust boundary from inside the model — where it cannot exist — to a control plane where it can, and make each checkpoint independently sufficient and fail-closed. The measurable result is a change in outcome: from an undetected instruction executed with the agent's full authority to a classified, constrained, and logged event. That is a smaller claim than immunity, and it is one you can actually substantiate with evidence.

Continue reading

← Back to blog