رفض الوكلاء الوسيطين غير الموثوقين: معماريات لتنظيم الوكلاء الآمن من ناحية الذاكرة
كيفية تأمين تنظيم الوكلاء دون ثقة بالوسطاء: runtimes موثقة، صناديق رمل لكل وكيل، حالة حتمية، بروتوكولات مسح، وتشفير نهاية إلى نهاية.
The Proxy Is the Risk, Not the Product
If an agent stack leaks, it tends to leak through a middleman. Reverse proxies, shared runtimes, app stores that wrap your build in a convenience shell—these are the quiet bottlenecks where memory is reused, billing meters tick, and policies get injected. That’s not paranoia; it’s a reading of the failure modes that keep repeating.
A proxy is billed as insulation: put the fragile things behind a layer that soaks up attacks and smooths operations. The trouble is that agents carry state. Scratchpads, tool results, prompts, embeddings, session keys. When intermediaries hold or transform that state, they become single points of accidental data exposure, cost shock, and policy gatekeeping. We’ve seen how classes of bugs in reverse proxies can produce memory disclosure across tenants. Cloudbleed made that clear years ago, and the pattern continues to crop up across shared infrastructure. Meanwhile, platform verification has tightened—what can run, how it runs, who can ship it—and teams are waking up to SaaS bills outpacing their mental models of use. Together, that’s a three-front problem for agent orchestration security.
This essay argues for a different baseline: architectures that assume intermediaries are useful but untrusted. That stance pushes security down into the runtime, up into the serialization layer, and sideways into the network fabric. The goal is not to eliminate proxies or platforms. It’s to stop them from holding secrets, defining your reliability, or writing your cost story.
What Goes Wrong When Agents Meet Intermediaries
Agent stacks are unlike classic web apps in a few ways that matter:
- They accumulate context across steps, tool calls, and retries. That context tends to be big, mutable, and sensitive.
- They fan out across providers and protocols—LLM APIs, vector stores, schedulers, payment rails—and glue that work back together.
- They use scratch memory heavily, not just durable storage. And scratch memory is where intermediaries bite.
Three failure modes recur.
First, reverse proxy memory leak. Whether from parser bugs, buffer reuse, or an optimization that trims one tenant’s response and slices into the next, the class of fault is simple: a shared component reuses memory in ways that can expose prior content. The severity varies—some incidents are narrowed to whitespace and headers; others spill payloads—but the trust boundary is breached. If part of your agent’s working set transits that component in plaintext, it is at risk by construction.
Second, shared runtimes blur isolation. Serverless platforms and extensions that run your code in a multi-tenant process model can cross-contaminate memory through error paths or misconfiguration. Even without a bug, lifecycle reuse (warm starts) can leave residual data if the language runtime doesn’t eagerly zero memory. Managed frameworks hide a lot of magic. They do not guarantee strong isolation unless isolation was the original design objective.
Third, platform coercion. App stores, plugin catalogs, and SaaS layers route your agent traffic through metering, verification, and policy enforcement they control. That can be helpful for safety and abuse prevention. It can also ratchet cost and veto product choices without warning, because the enforcement sits in the middle of your critical path.
The consequence: one misbehaving middleman can breach confidentiality, mutate behavior, and explode spend. You can bolt on monitoring and rate caps, but you still have a data path that assumes the proxy is honest, available, and stable.
A Different Baseline: Distrust Intermediaries by Default
Start with a crisp threat model.
- Assume every intermediary can read or modify traffic it terminates.
- Assume shared compute can retain and resurface memory you didn’t intend to persist.
- Assume policy or billing changes can be pushed into a managed middlebox without negotiation.
Then set constraints that fall out of those assumptions:
- Agents should not rely on intermediaries for confidentiality. Message payloads must remain opaque to transit layers.
- Agent state should be locality-scoped and bounded. Anything sent across process or host boundaries must be serializable, deterministic, and minimize secrets.
- Memory should be allocated, labeled, and wiped with evidence. If it can’t be wiped, it is encrypted with a key that can be.
- Networking should be proxy-resistant: usable through proxies, but cryptographically independent of them.
With that baseline, reverse proxies can still help with caching, load smoothing, and DoS posture. They simply stop being sources of truth.
Attested Native Runtimes: Shrink the Trust Boundary to the Code You Ship
When an agent is a graph of tools and models glued by a planner, your runtime is the blast radius. If you cannot say what binary ran, with what dependencies, on what host class, you are not in control of agent orchestration security.
Attested runtimes are the core. Two parts matter.
- Memory-safe implementation. Choose runtimes and languages that do not invite undefined behavior in the heap: Rust, Go, or a hardened WebAssembly engine with capability-based host calls. It won’t eliminate all risk, but it rules out entire bug classes.
- Measured execution. Use signed artifacts and a boot chain you can interrogate. That can be simple—verifying a binary signature at launch and checking a hash against a transparency log—or sophisticated—remote attestation with a TEE, TPM quotes, and policy that pins acceptable measurements.
Attestation is not only for enclaves. Even without hardware support, you can derive value:
- Reproducible builds and hermetic packaging reduce drift.
- Hash-pinned dependencies and container images provide an audit trail.
- Runtime checks (e.g., verifying a signature before loading a tool plugin) make the agent graph explicit and reviewable.
TEEs add stronger guarantees by letting a remote verifier confirm a measurement produced by hardware. They bring tradeoffs: limited memory, side-channel research that continues to evolve, and operational complexity. They shine for key material and small critical loops, such as a planner that decrypts and re-encrypts prompts locally. For heavy model inference, you likely pair TEEs with isolating hypervisors and rely on message-layer cryptography to protect payloads in flight.
Attestation should extend to the orchestration pipeline:
- Job workers that pop agent tasks off a queue should verify their own provenance and expose it in logs.
- Tool adapters (search, database, payments) should be separate, signed components with narrow capabilities, not dynamic imports at runtime.
- Configuration should be signed and pinned as well. If a proxy injects a new endpoint or header, your runtime should reject it unless it matches policy.
This shrinks your trust boundary to code you can reason about and components that can prove what they are. It also sets you up to defend against coercion: even if a platform requires a proxy hop, your runtime decides what to reveal, not the other way around.
Per-Agent Memory Sandboxes: Isolation, Not Convention
Most agent frameworks default to pragmatic sharing. A pool of workers handles many agent sessions. A shared cache speeds up tokenization and tool results. That is fine for performance; risky for memory.
Move to hard isolation. The unit is the agent session.
- Process-per-session where possible. On modern hosts, a short-lived process is cheap. A process gives you an address space to wipe, an OS scheduler to enforce quotas, and a crash boundary.
- If process-per-session is too heavy, use an engine that provides real isolates. WebAssembly runtimes and language runtimes with independent heaps and module-level capabilities can work—provided you lock host calls down. Treat host capabilities as explicit capabilities, not ambient authority.
- Track memory labels. Not every buffer is equal. Tag buffers that hold secrets (keys, PII, customer prompts) and run zeroization on drop. Force allocators for secret buffers to mlock to avoid swapping, and fail closed if the OS can’t honor it.
Give each agent session its own key material. Derive a per-session data-encryption key from a master held in an HSM or cloud KMS, bound to the attested runtime measurement. All scratch files, temporary vector indexes, and on-disk spills are encrypted with that key. The key lives in memory only as long as the session. When the key is gone, crypto-erasure wipes the data even if you miss a cleanup path. That is the memory-safe agent architecture move that pays off again and again.
Keep caches out of the trust path. That big embedding cache everyone shares to save money? Move it behind a process boundary and a narrow API that returns only what the caller can see, and encrypt entries with per-tenant or per-session keys. Or accept the privacy risk explicitly and never put secrets in that cache. What you cannot do is carry on with an in-process LRU and assume conventions will hold once the system is under load.
Tooling matters, but discipline matters more. Don’t let tools register arbitrary callbacks into the agent’s heap. Give them an RPC surface that enforces data shape and size, and treat every tool as if it were a network hop.
Deterministic Serialization: State That Travels Without Bleeding
Agent orchestration lives on serialization. Plans, tool invocations, and partial outputs must be shipped between processes and machines. If serialization is sloppy, you will leak state, misroute data, and create memory that refuses to die.
A few rules help:
- Choose a canonical wire format and stick to it. JSON can be made canonical; CBOR or Protocol Buffers can enforce stronger typing. The key is that there is exactly one representation of a given state.
- Do not serialize closures, pointers, or implicit environmental state. The only things that leave a process are plain data structures with fixed schemas. If a tool needs a capability, pass a capability token, not a function pointer.
- Version your schemas and make migrations part of your agent planner, not a mysterious side effect. If you change the shape of a memory record, you should be able to replay an agent’s event log deterministically across the change.
- Treat agent state as an append-only log with content-addressed segments. That lets you reference past steps without copying blobs around, and it allows garbage collection to be auditable.
Deterministic serialization has a security dividend. If a reverse proxy memory leak exposes fragments, the damage is contained and recognizable—bounded values, redacted fields, and checksums that fail if a proxy tampers. And if a platform tries to inject or reorder steps, your runtime can detect mismatches between the signed state sequence and the traffic it sees.
It also makes debugging less invasive. You can ship logs to observability systems without raw prompts or tool results, because the event graph and hashes are enough to reconstruct behavior inside a safe environment when needed.
Provable Wipe Protocols: Memory That Tells the Truth When It’s Gone
Wiping memory sounds easy. Zero the buffer. Close the file. In practice, runtimes optimize away zeroization, GC defers frees, filesystems journal blocks you never see, and caches cling to the best bits.
This is where cryptographic erasure and protocol-level guarantees matter.
- Encrypt everything transient with short-lived keys. If you treat every scratchpad as encrypted-at-rest, your deletion story is, “this key no longer exists.” That works across process crashes and OS reboots. It also works across mistakes—if the scratchpad was accidentally copied, the copy remains unreadable.
- Pin secrets to explicit lifetimes. Associate keys to agent session IDs and step counters. When a step finishes, the subordinate key for that step is dropped. When the session completes, the session key is dropped. At process exit, zeroize any remaining key slots before returning control to the OS.
- Prove wipes with attested logs. The runtime records a wipe event with a signature bound to its measurement. Your control plane verifies that the expected wipes occurred. Where required, expose proofs to auditors that memory handling is not a best-effort promise but a policy with evidence.
- Harden against swapping and coredumps. Lock secret pages, disable core dumps for processes with tagged memory, and ensure crash handlers scrub tagged regions before yielding. If your environment forbids those knobs, treat it as an untrusted host for secrets. Do not place prompts, keys, or PII there.
- Don’t rely on destructors in managed languages to wipe secrets. Runtimes that move and copy objects can leave remnants. Use specialized libraries that treat secret buffers differently, with constant-time operations and explicit zeroization.
When you put wipe protocols under policy, the debugging culture changes as well. Engineers stop sprinkling print statements and start leaning on redacted structured logs and deterministic replays. That is a healthy trade.
Proxy-Resistant Networking: End-to-End or It’s Not Confidential
A reverse proxy is a great place to terminate TLS if you’re optimizing for convenience. It’s the wrong place to terminate confidentiality.
Design message-layer security as if the transport were always compromised. That means:
- Encrypt request bodies at the application layer with recipient public keys before they ever touch a proxy. The proxy sees metadata it needs to route, and nothing else. On the return path, do the same.
- Use mutual authentication. mTLS is the obvious choice within your control plane. Across the open internet, use signed requests with short-lived tokens bound to a specific message and recipient key, so a replay at the proxy is harmless.
- Pin keys, not endpoints. If a platform forces a proxy hop or DNS trick, your agent runtime verifies the recipient’s key. No key, no secrets. This stance survives domain-fronting and middleboxes that add or strip headers.
- Avoid MITM inspection for sensitive channels. In regulated environments where proxies are mandatory, negotiate carve-outs where payloads are opaque by policy, with compensating controls at the endpoint. If that is impossible, do not send secrets through that path.
This is not about skirting enterprise controls. It is about clean separation of concerns: proxies route and throttle; endpoints protect privacy. The best corporate networks in finance and government already draw this line. Agent orchestration should, too.
For agent-to-agent chatter, avoid ad hoc RPC. Use capability-bearing tokens that constrain what the callee can do. Bind capabilities to a narrow scope: tool X, on input Y, for session Z, until time T. The token is signed by the orchestrator and is useless if transplanted to another context, which blunts the damage if a proxy logs it.
If you must traverse third-party APIs that inspect content, assume inspection will happen, and never send more than the minimum. Redact aggressively and split flows: sensitive computation local or on a trusted endpoint; non-sensitive augmentation through the service.
These moves add latency. You pay a few extra milliseconds for crypto. The response is not to give up; it is to measure and adjust batching and concurrency. Reliability improves when you are not praying a cache in the middle remains honest.
Cost and Policy Coercion: The Other Two Spikes on the Same Spear
Security failures get attention; cost and policy pain linger in ticket queues until the quarter ends. Proxies and managed layers complicate both.
Billing shock happens when the meter lives in the middle. Platform convenience often comes with opaque pricing curves: escalators for concurrency, data egress charges at layer 7, hidden minimums on idle listeners. Agents are bursty. A planner that fans out to five tools and retries twice can turn into dozens of calls per user input. If a proxy ties cost to those tiny bursts, your mental arithmetic will be wrong.
A proxy-resistant approach helps you reclaim control:
- Do metering at the orchestrator and treat the proxy as a pass-through. Build internal cost models on message counts and sizes at the application boundary you actually own.
- Enforce budgets in the runtime. Refuse to fan out if the step budget is exhausted. Fail gracefully before a provider’s hard limit fails you at a higher rate.
- Keep local fallbacks. For common tasks, run a local model or cache to smooth the long tail, so a sudden price change upstream does not blindside operations.
Policy gatekeeping is less about money and more about pace. App stores and plugin catalogs are tightening verification for good reasons—safety, abuse mitigation, ecosystem stability. But if a store can remotely disable your adapter or throttle a capability, product behavior is the hostage.
To prepare:
- Insist on exportable adapter contracts. Your tool integrations should build from open protocols you can run on your own if needed. If a vendor’s SDK wraps a network path you cannot see or replace, that is a strategic risk.
- Keep an internal registry for tools and models. Even if you publish to public catalogs, your orchestrator should prefer references to vetted artifacts under your control.
- Separate policy from execution. Safety checks, filters, and rate limits should live in code you ship and attest, not exclusively in a remote proxy that can change overnight.
None of this rejects platforms. It simply avoids fusing your product to their private rails.
The Counter-Argument: Centralized Middleboxes Reduce Risk
A fair critique goes like this: middleboxes concentrate expertise. A big reverse proxy can absorb attacks better than your slender agent runtime. A managed gateway is where compliance teams put logging and controls. Fragmenting responsibility across runtimes and message-layer crypto complicates life for defenders and auditors.
There is truth here. Centralizing TLS termination, IP reputation, and coarse rate limiting helps. It cuts down exposure to trivially automated attacks. It gives teams a single place to patch. Observability is easier when all traffic flows through one visible choke point.
The reply is not to yank proxies out. The reply is to strip them of privileges they do not need. Let them keep their strengths—routing, shielding, coarse policy—while taking confidentiality, fine-grained authorization, and sensitive state out of their hands. You can still ship rich logs by recording hashes, event graphs, and metadata. You can still run a WAF without giving it your customer prompts. You can still embrace zero trust while using centralized infrastructure.
And you will sleep better knowing that a memory disclosure in a proxy can spill headers and metadata, not raw agent state.
Migration Paths: From Proxy-Centric to Proxy-Resistant Without a Rewrite
Enterprises don’t refactor architectures on a hunch. The path to memory-safe agent architectures runs through a few practical moves you can make without pausing delivery.
Start with contracts, not code. Define the agent state model as a versioned schema and commit to deterministic serialization. If you need to migrate a dozen handlers and queues to use it, do that first. Everything else builds on this bedrock.
Introduce per-session keys early. Even if you don’t encrypt every buffer on day one, switch scratch files and on-disk spills to envelope encryption with keys bound to session IDs. The changes are localized and measurable. You will immediately see the shape of your scratch world, which is a gift during audits.
Pull tools behind capability-bearing RPC. Wrap your in-process adapters in a thin RPC server that enforces data shapes, quotas, and capabilities. You can run it on the same host initially. The point is to make tool boundaries explicit so isolation can grow later without rewrites.
Attest what you can attest. Sign binaries. Pin container images. Export runtime measurements to logs. If your platform supports remote attestation, adopt it for the orchestrator and key-handling components. Start small, with the planner and key store. Build familiarity before moving heavier parts.
Push message-layer crypto on one critical path. Pick a high-sensitivity call—say, the prompt that includes customer identifiers—and encrypt it end-to-end. Prove to yourself that operations can live with proxies that are blind to the payload. Then expand coverage.
Measure cost where it matters. Set up internal metering hooked to the agent runtime, not the proxy logs. Make planners budget-aware. Once you can see spend at the application level, platform billing surprises stop being surprises.
Alongside, update procurement language. New contracts with vendors and platforms should include:
- The right to use message-layer encryption that keeps payloads opaque to intermediaries.
- Access to key retrieval or attestation hooks sufficient to bind capabilities to runtime measurements.
- Clear egress pricing for proxy-mediated calls and hard caps or alerts on spend.
In regulated multi-entity environments—common in the Gulf where groups run multiple regulated units under one umbrella—the impact compounds. Clean boundaries let you route traffic through shared infrastructure without drifting into shared memory. When external audits drill into how agent state moves across entities, you have evidence, not folk wisdom.
A Concrete Reference Flow
It helps to see how these patterns compose. Consider a customer-support agent that triages tickets, queries a knowledge base, and drafts responses.
- A session starts when a user opens a thread. The orchestrator spawns a process for the session and derives a session key from a KMS. The derivation is bound to an attested measurement of the runtime. The process locks secret pages to avoid swapping.
- The ticket payload is serialized into a canonical format, redacted fields are marked, and the body is encrypted at the message layer for the storage service. The reverse proxy sees headers for routing and a fixed-size ciphertext body.
- The planner runs local checks, then calls a model provider. The prompt that includes any PII or confidential context is encrypted with the recipient’s key before it travels. The call uses mTLS, and the orchestrator pins the provider’s public key. The platform’s edge proxies terminate transport TLS but cannot read the body.
- Tool adapters for the knowledge base and CRM are separate signed binaries. The orchestrator issues capability tokens scoped to read-only queries for specific records. Tokens expire quickly and cannot be replayed in a different session.
- Scratch embeddings are cached to disk, encrypted with the session key. The cache process is firewalled to the local host. Another session cannot read them; another process cannot even parse them without the key.
- When the agent composes a draft, the event log references content-addressed segments. Logs shipped to observability contain hashes and event types, not raw content.
- On session end, the process zeroizes key slots, deletes the envelope keys from the KMS, and emits signed wipe events. A background janitor prunes encrypted scratch files by age; crypto-erasure has already made them inert.
A reverse proxy can still balance load, absorb attacks, and centralize coarse logging. If it leaks a buffer, it spills only metadata. If the platform tightens policy on a tool, you can swap to an internal adapter with the same contract. If the provider changes billing curves, your runtime can throttle and fall back to a local model for drafts rather than blasting requests into a new tier.
Pitfalls and Practical Limits
Not every team can flip all of these switches. A few caveats help avoid disappointment.
- TEEs are not a panacea. They complicate operations and create new surface area. Use them for key handling and narrow logic, not as a blanket for heavy compute.
- Message-layer crypto depends on key management hygiene. Compromised keys collapse the model. Invest in a KMS with role separation, rotation, and transparency.
- Deterministic serialization can feel rigid. It slows down improvisation. That friction pays dividends when you’re debugging or proving non-leakage to an auditor, but plan for it in delivery timelines.
- Isolation costs money. Process-per-session eats CPU; per-tenant caches multiply storage. Start with high-sensitivity paths and scale outward.
- Observability needs a refresh. If you cannot read payloads in your logs, you need better structured events and replay tools. Build them early so engineers do not create their own shadow logging with secrets.
These are tradeoffs, not ideology. The question is whether the control you gain over security, cost, and policy is worth the overhead. In most agent deployments that handle real customer data, it is.
Why This Matters Now
Memory disclosure bugs at the edge have a long history. They are not going away. Every time a shared layer grows more features—smart parsing, compression tricks, programmable middleware—the surface grows. At the same time, platform verification and policy enforcement have tightened. App stores and managed ecosystems are curating what gets to run, and under what rules. And usage-based pricing interacts badly with agent burstiness. None of these trends is hypothetical. Teams have watched bills spike, builds blocked, and payloads skimmed by components they do not control.
Treating intermediaries as untrusted changes the energy of all three. Memory safety becomes a property of your runtime and your state model. Cost becomes something your orchestrator can see and cap. Policy remains important but cannot rewrite your product overnight from a distance.
In the UAE and across the Gulf, this is especially relevant for organizations that operate across regulated entities or jurisdictions. A proxy may be mandated. A shared platform may be efficient. The discipline is to let them move packets and enforce high-level rules without turning them into containers for secrets. The audit story becomes cleaner. The architecture becomes portable when the regional footprint grows.
The Sharp Edge
The habit of trusting middleboxes grew when apps were stateless and secrets were few. Agents are not like that. They carry memory by design. If you let intermediaries handle that memory, you’ve already answered your own security question—and not in your favor.
Keep using proxies, platforms, and stores. But stop giving them intimacy. Put attested runtimes at the core, isolate each agent’s memory, serialize deterministically, wipe with proofs, and ship encrypted payloads that do not ask a proxy for discretion. That is how agent orchestration security grows up.
Reverse proxies can still leak. Platforms can still tighten. Billing can still surprise. If your stack is built with proxy-resistant networking and memory-safe agent architectures, those events hurt—then bounce. That’s the point.