Full paperThis is the long version, with evidence classes, adversary model and citations. The plain-language summary is How LLM serving infrastructure gets broken into, and it takes about five minutes.

Thesis

LLM serving infrastructure creates security boundaries out of performance mechanisms. Cache addressing, scheduling and artifact loading are not access-control components, and were not designed as any, yet in a shared deployment they determine who can reach whose data. A secure deployment therefore has to bind identity at ingress, carry it across every internal plane, and verify that each performance optimization respects the same boundary.

Everything below follows from that one observation.

About this document

This is an architectural threat model, not a vulnerability disclosure. The analysis names no products and reports no findings. Every category describes a class of defect that arises from how inference systems are built, along with the questions to ask of your own stack and the controls that answer them.

Public advisories and research are cited in the references so that the evidence claims can be checked. Vendor-neutral is not the same as source-neutral: the categories are described by mechanism, and the citations exist so a reader can verify that a class is real rather than take it on assertion.

It is written for the people who deploy and review this infrastructure: platform engineers running a serving cluster, security engineers asked to sign one off, and researchers looking for where the unexamined surface is.

The ten categories are a review framework, not a universal severity ranking. Their priority depends on deployment topology, tenant model, exposed interfaces, and what privileges are available after a compromise. The numbering is navigational.

What this is not. It is not a survey of which projects are vulnerable, and it contains no undisclosed vulnerability information. Where a class has been demonstrated publicly, it is described by mechanism rather than by vendor. Nothing here requires you to trust an assessment of someone else’s code.

Evidence classes

Each category carries a label. The standard for each is fixed, so the labels mean the same thing throughout.

LabelStandard
Incident-backedA public exploitation report, confirmed production compromise, or operator postmortem exists, with a primary source
Advisory-backedA CVE, published vendor advisory, or maintainer-confirmed vulnerability exists, without a known exploited incident
ArchitecturalThe class follows from the design and is supported by research or vendor engineering guidance, without a public implementation-specific finding

Architectural indicates a mechanism-derived risk requiring deployment-specific validation. It is not evidence of a defect in any particular implementation, and equally it is not a claim that the class is theoretical: it means the public record has not caught up, which historically has been a statement about timing rather than about safety. Every label is backed by a numbered citation in the references.

What a citation means here. It establishes that the mechanism has occurred in at least one real implementation. It is not a claim that any particular system is currently affected, nor that the cited project is representative.

1. Why this stack is different

Inference infrastructure is often reviewed as though it were ordinary web infrastructure with a GPU attached. It is not, and five properties account for most of the difference.

Caching is not an optimization here, it is a shared data structure holding user content. A prefix cache exists to let one request reuse work done for another. That is its function, not a side effect. The moment two principals can reach the same cache, reuse and disclosure are the same mechanism viewed from different sides.

Identity is usually derived, not asserted. Cache entries, KV blocks and scheduling decisions are addressed by values computed from request content: token hashes, block hashes, prefix chains. Anything not included in that derivation is invisible to the lookup, including who is asking.

Artifacts are executable. Model files, adapters, tokenizer configs, dataset descriptors and chat templates are all inputs that some component will parse, and several common formats carry references or expressions that the parser will follow or evaluate. The boundary between data and code is thinner here than almost anywhere else in modern systems.

The internal plane is large, chatty and historically unauthenticated. Disaggregated serving splits prefill, decode, routing, cache tiers and metadata services across processes and hosts. Many of these components were written when the deployment assumption was a single trusted cluster network, and that assumption is frequently still in the code and the defaults.

The control plane is Kubernetes. These systems ship operators, custom resources and Helm charts. That makes cluster-level primitives (service account tokens, node metadata, admission policy, namespace scoping) part of the inference attack surface, and they are usually reviewed by a different team than the one reviewing the Python.

2. Reference architecture

The categories below refer to these roles rather than to any product.

Reference architecture of an LLM serving deployment Clients cross a trust boundary into an ingress gateway, which authenticates the caller against an identity source and derives a signed authorization context. That context is carried down every internal hop: to the scheduler, to both model runners, to the peer-to-peer transfer plane and to the shared KV cache tiers. The runners also load artifacts and make outbound fetches. A platform control plane and an observability plane run alongside every layer of the stack. PLATFORM / CONTROL PLANE CRDS · RBAC · SECRETS · WORKLOAD IDENTITY · ADMISSION OBSERVABILITY METRICS · TRACES · LOGS Clients / tenants many principals, one endpoint TRUST BOUNDARY IDENTITY AND AUTHORIZATION CONTEXT BOUND HERE Ingress and gateway authenticate · authorize · derive signed context claims Identity source IdP, API tokens, mTLS, workload identity Scheduler / router dispatches on policy and isolation context Artifact store models, adapters, tokenizers, configs Model runner A prefill / decode Model runner B prefill / decode Outbound fetch remote artifacts, media, adapters Transfer plane authenticated KV movement KV cache tiers GPU · host RAM · disk · object store: physically shared, partitioned only if you partition it request and data path signed authorization context: tenant · project · cache-isolation namespace
The green dashed path is the signed authorization context derived at ingress. Invariants 1 and 2 are the claim that it survives every hop that touches shared state, and most of the categories below are what happens where it does not. The two side rails are planes that touch every component and are usually reviewed by a different team than the request path. Both runners load artifacts and make outbound fetches; only one of each is drawn, to keep the picture readable.

Two observations about this picture drive most of what follows.

The gateway is typically the first component that can reliably bind a request to an authenticated caller identity. A service mesh, workload identity system or signed downstream context can carry that binding further, but something has to establish it first. Everything past it works with derived identifiers. If authorization context is not carried across that line, it does not exist downstream, and no amount of correctness in the cache layer will recreate it.

The cache tiers and the transfer plane hold multiple principals’ data in one addressable space by design, which makes them isolation boundaries whether or not they were built as any. They are not the only such places: request logs, traces, metrics backends and queues accumulate multi-principal data too, and they are frequently the least reviewed component in the diagram. What distinguishes the cache is that reuse across principals is its purpose rather than a side effect of observability, so the failure is silent and looks like success.

Four invariants

Six of the ten categories are violations of four properties, and it is worth seeing them as one system rather than as separate findings.

  1. Identity propagation. The authenticated principal and its authorization namespace survive every hop that touches shared state.
  2. Context-complete addressing. Stored or reused inference state is keyed by all security-relevant execution context, not only by content.
  3. Authenticated peer relationships. Internal components authorize on cryptographic workload identity, never on self-asserted routing metadata.
  4. Fail-closed enforcement. A component that cannot honor a security control refuses the request rather than serving it downgraded.
InvariantBroken by
1. Identity propagationINF01(a), INF06
2. Context-complete addressingINF01(b), INF01(c)
3. Authenticated peer relationshipsINF02, INF03
4. Fail-closed enforcementINF10

Invariant 2 has a limit worth stating: correct addressing is necessary but not sufficient. A key separates principals only if lookup, eviction and storage semantics all enforce the separation the key expresses. Addressing identity and authorization enforcement are different things, and INF05 exists because the first can be right while the second still leaks through timing.

The remaining four categories are not identity problems. INF04, INF07, INF08 and INF09 concern execution, parsing and privilege, and are governed by ordinary isolation and least-privilege practice rather than by anything specific to inference. They are in scope because this stack reaches them through unusual entry points, not because the controls are novel.

Adversaries

Categories are only testable against a stated attacker. Five are referenced throughout.

AdversaryCapability
A1Remote unauthenticated callerReach exposed routes, measure response timing
A2Authenticated low-privilege tenantIssue chosen prompts, reference permitted artifacts, observe service behavior
A3Internal workload attackerHolds a pod foothold, can reach cluster-local services
A4Artifact supplierInfluences a model, adapter, tokenizer, media or dataset input
A5Control-plane attackerHolds a compromised service account or bypasses admission policy

Note the preconditions this makes explicit. Cache side channels need co-residency or a shared cache tier and are an A2 problem. Control-plane escalation generally presumes an A3 foothold obtained some other way, which is why it multiplies the severity of every other category rather than standing alone.

Deployment applicability

Attacker capability depends on how the system is deployed, and not every category applies to every shape.

CategorySingle hostMulti-nodeKubernetes fleetAgent or tool-enabled
INF01, INF05 cache identity and side channelsIf multi-tenantYesYesYes
INF02, INF03 internal planes and peer identityLimitedPrimaryPrimaryYes
INF04 host and accelerator memoryYesYesPrimaryYes
INF06 routing metadataIf a gateway existsYesPrimaryYes
INF07, INF08 artifacts and pathsYesYesYesPrimary
INF09 control planeNoPartialPrimaryYes
INF10 silent control removalYesYesYesYes

3. The categories

INF01. Cache identity that fails to bind security context

Advisory-backed for (c)Architectural for (a) and (b)Adversary A2

Mechanism. Cache lookup keys are derived from request content: token sequences, prefix chains, block hashes. A key is a security boundary in a shared deployment whether or not it was designed as one, and it fails in three distinct ways.

(a) Authorization namespace omitted. The key contains no component derived from who is asking. Two principals sending the same content address the same entry. Reuse across the trust boundary follows automatically and no attacker action is required to cause it. This is the intended behavior of the cache operating on unintended inputs.

(b) Version and variant context omitted. The key binds tokens but not model revision, tokenizer revision, adapter or LoRA identity, or multimodal input identity. Entries then collide across configurations that should not share state, which is a correctness problem that becomes a security problem when the configurations belong to different principals.

(c) The identifier itself is weak. Even with the right inputs, a truncated or narrow identifier admits crafted collisions, letting one entry displace or be served in place of another. This subtype has a published advisory behind it [1]; the other two are architectural.

Distinguishing these matters because the fixes differ and do not substitute for one another. Width addresses (c). Only binding authenticated identity addresses (a).

Why it recurs. Cache keys are written by people optimizing hit rate, and every field added to a key reduces hit rate. Isolation inputs therefore look like a cost. The failure is usually not a refusal to add them; it is that a key is designed once, in a single-tenant context, and never revisited when the deployment becomes shared.

Ask your stack.

  • Enumerate every field in your cache key. Which of them is derived from who is asking rather than what is being asked?
  • If your engine offers a per-request isolation input, does every cache tier and every storage backend actually incorporate it, or only some?
  • When a request carries an isolation input your cache layer does not understand, what happens?
  • Does the key bind model revision, tokenizer revision, and adapter identity, or only tokens?
Controls

Derive storage identity from an authorization namespace bound at the gateway, not from a caller-supplied value alone. A caller-chosen salt is a useful mechanism but is not by itself a tenant boundary, since a caller can choose another caller’s value; bind it to authenticated identity at ingress. Keep the namespace in the key that reaches storage, not only in an in-memory index.

INF02. Unauthenticated internal control and data planes

Incident-backedAdversary A1, A3

Mechanism. Coordination endpoints, metadata services, metrics and profiling ports, cache coordinators and job submission interfaces bind to all interfaces with no authentication, on the stated assumption of a trusted network. In practice these land on cloud VPCs, shared clusters and occasionally public addresses.

Why it recurs. The assumption is usually documented, which converts it from a defect into a deployment requirement in the maintainers’ view. That is a defensible position for a library and a dangerous one for a product, and the gap between those two readings is where these incidents live. Publicly documented mass-exploitation campaigns against AI compute clusters have followed exactly this shape [2][3]: an unauthenticated management interface, reachable, doing what it was designed to do.

Ask your stack.

  • Inventory every listening socket in a running deployment, including sidecars. For each: what authenticates the caller?
  • Which of those are bound to 0.0.0.0 by default rather than by your configuration?
  • Do you have a NetworkPolicy per workload, or a flat pod network?
  • If an attacker held a foothold in one pod, which of these would be reachable?
Controls

Bind internal services to loopback or a private overlay. Require mutual authentication on any interface that moves cache state or accepts work. Default-deny network policy between namespaces. Treat “assume a trusted network” in documentation as a finding in its own right, and record who owns producing that network.

INF03. Self-asserted peer and tenant identity

ArchitecturalAdversary A1, A3

A note on what is and is not evidence for this. Published remote-execution advisories exist on KV transfer and coordination services [4][5], but their root cause is network reachability plus deserialization, which belongs to INF02 and INF07. They are not evidence that a peer-supplied identity was treated as authorization. That distinction is the whole point of this category, so it is classified architectural until an advisory demonstrates the mechanism directly [6].

Mechanism. A request or a peer supplies the value used to decide who it is or where its data should come from: a peer address for a cache transfer, an engine or instance identifier, a tenant field in an RPC. The receiving component validates the shape of that value and treats it as authorization.

Why it recurs. In a disaggregated system, components genuinely do need to tell each other where things are. The design error is using the same field for routing and for authorization. Handshakes built for correctness (do we agree on the model, the dtype, the layout?) are frequently mistaken for handshakes that establish trust.

Ask your stack.

  • For every identifier a component receives over the network, ask whether it is checked against something the sender could not have chosen.
  • Can a client influence which peer a worker connects to, or which cache namespace it reads?
  • Is any tenant identifier passed as a plain parameter rather than derived from a credential?
Controls

Cryptographic workload identity, so a peer proves what it is rather than naming it. Declarative peer allowlists derived from cluster topology instead of dynamic self-registration. Never let a request nominate its own data source.

INF04. Host and accelerator memory isolation failure

ArchitecturalAdversary A3

Mechanism. Performance work pushes these systems toward shared memory segments, host IPC, and pinned or reused device memory. Each of these is a channel that crosses a process boundary by design, and bounds checking on shared-memory registration is a recurring source of memory-safety defects in native code [6].

Why it recurs. The performance gain is real and measurable; the isolation cost is not visible in any benchmark. hostIPC: true in a manifest is one line and removes a boundary the rest of the architecture assumes.

Ask your stack.

  • Does any workload set hostIPC, hostNetwork, hostPID, or privileged?
  • Which shared-memory segments exist at runtime, and what are their permissions?
  • What is your device-buffer reuse policy between tenants, and has it been stated anywhere? Treat this as a question to answer rather than an assumed defect: cross-tenant disclosure through accelerator memory remanence is not an established public class.
Controls

Reject privileged and host-namespace-sharing pods at admission unless explicitly justified. Scope memory-backed volumes to the pod. Treat native shared-memory registration paths as requiring the same review as any other parser of untrusted length fields.

INF05. Observable cache behavior as a side channel

Advisory-backedAdversary A2

Distinct from INF01. INF01 is an authorization and storage-identity failure. INF05 is an observable side channel that persists even where direct access is correctly denied. Fixing one does not fix the other.

Mechanism. A cache hit is faster than a miss. Where an attacker can submit candidate content and observe latency, scheduling behavior, or exposed metrics, the cache becomes an oracle for what other principals have sent. This is the best-studied class in the whole taxonomy and has published vendor advisories [7] as well as a substantial research literature [8][9][10][11] behind it.

Why it recurs. It is inherent to sharing. Eliminating cross-principal cache timing leakage outright means eliminating cross-principal sharing, which is the entire economic argument for the cache. Partitioning and access-governed reuse materially reduce exposure but need verification rather than assumption, since leakage can arise from KV state, semantic caches, memory allocation, batching and scheduling independently. So this class is managed rather than eliminated, and the management decision is frequently never made explicitly.

Ask your stack.

  • Can an unauthenticated or low-privilege caller measure first-token latency precisely?
  • Are cache hit and miss counters exposed per-entry or per-tenant on a metrics endpoint?
  • Is prefix reuse permitted across trust domains, and was that a decision or a default?
Controls

Scope reuse to a trust domain rather than globally. Consider selective sharing policies for content that is genuinely public (system prompts, shared documents) with isolation for everything else. Restrict metrics granularity and access. Accept that timing noise is mitigation, not prevention.

INF06. Routing metadata treated as trusted input

Advisory-backedAdversary A1, A2

Mechanism. Gateways and routers accept headers or request fields that influence internal destination selection: target pod, model rewrite, backend hints, cache routing keys. If these are not stripped at the trust boundary, a caller steers internal traffic [12][13].

Be precise about which of two things you have. Where the header only selects among legitimate backends, it is internal request-routing manipulation. It becomes server-side request forgery only when it can make the service open a connection to an attacker-selected or policy-bypassing destination, which is typically the outbound artifact or media fetch path rather than backend selection.

Why it recurs. These headers are genuinely useful for internal components, and the same header namespace typically serves both internal and external callers. Sanitizer lists are maintained by hand and drift behind the features that add new headers.

Ask your stack.

  • What is the allowlist of headers permitted to cross from ingress into the mesh, and when was it last reconciled against the features that read headers?
  • Can a caller influence backend selection, model identity, or cache namespace via a header?
  • Does the outbound fetch path (artifacts, adapters, remote media) validate destinations against an allowlist, including after redirects?
Controls

Strip-by-default at ingress with an explicit allowlist. Reconcile that list in CI against the set of headers any component reads. Validate outbound fetch targets after redirect resolution, not before.

INF07. Artifacts and configuration as executable input

Incident-backedAdversary A4

Mechanism. Four distinct sub-cases, and they are worth separating because the controls differ [13][14].

Deserialization. Model checkpoints and cached artifacts in formats that carry executable constructs, loaded by components that treat the local cache or the artifact store as trusted.

Template evaluation in a data path. Configuration fields, chat templates and dataset descriptors rendered by a template engine. If the engine is not sandboxed, a field that looks like a numeric offset or a URL is a code-execution primitive. The controlling question is whether the environment is sandboxed, and it is answerable by reading one line, but that line frequently lives in a dependency rather than in the project under review.

References inside the artifact. Several scientific and array data formats let a file declare that its actual contents live at another path, which the reader follows on open. This defeats every path-validation control that inspects arguments, because the path is not an argument. It is data inside the file.

Resource abuse through the parser. Decompression bombs, oversized media decoding, pathological archives and deeply nested structures exhaust CPU or memory before any application logic runs. This sits with the others because the entry point is identical, an artifact the system was asked to parse, but the control is different: limits and timeouts rather than sandboxing.

Why it recurs. Convenience formats win on developer experience. And the safety of a parser is frequently a property of a transitive dependency’s version, which nothing in the reviewed project reveals.

Ask your stack.

  • Which components parse artifacts uploaded or named by users, and what formats do they accept?
  • For every template render on a data path: sandboxed environment, or not? Check the dependency, and check the pinned version.
  • Do your loaders resolve references embedded inside artifacts, and are those resolved paths validated against an allowlist?
Controls

Prefer formats without executable constructs. Eliminate template evaluation from configuration parsing, or sandbox it explicitly and pin the version that does so. Validate artifact-internal references, not just API arguments. Parse untrusted artifacts in a process with no credentials and no network.

INF08. Artifact path resolution outside the intended root

Incident-backedAdversary A4

Mechanism. Storage initializers, model downloaders and cache backends construct local paths by joining attacker-influenced components: object keys, digests, manifest entries, layer names. Where containment is not enforced after resolution, writes and reads escape the intended directory. Publicly documented cases have reached arbitrary file write and code execution through exactly this route [15].

Why it recurs. Path handling is spread across per-backend implementations. One backend gets the containment check and the siblings do not, because the check was added in response to a specific report rather than to the class.

Ask your stack.

  • Enumerate every storage backend you support. Which of them enforce containment after path resolution? Diff the implementations against each other, not against the specification.
  • Are archive entries checked for traversal before extraction?
  • Is the resolved path re-validated after symlink resolution?
Controls

One containment helper, used by every backend, tested per backend. Resolve first, then verify the result is under the root. Extract archives with an explicit per-entry check.

Resolve-then-verify is necessary but not sufficient, because a symlink or a rename between the check and the write reopens the escape. Where practical use descriptor-relative filesystem operations so the check and the write refer to the same object, reject symlink traversal outright for untrusted extraction, and do the extraction in an unprivileged sandbox with no credentials.

INF09. Control-plane over-privilege

Incident-backedAdversary A3 escalating to A5

Mechanism. The initial defect gives execution or file read in a pod. What turns that into a cluster compromise is the environment: a mounted service account token with broad rights, a reachable cloud metadata endpoint, permissive admission policy allowing privileged pods and host mounts, cluster-scoped rather than workload-scoped credentials, and signing keys that permit minting further identity. This chain is the difference between an incident and a catastrophe, and the public record of agent-driven intrusion shows it traversed quickly once the first foothold existed [14].

Why it recurs. Operators are written to work across many cluster configurations, and broad permissions are the path of least resistance to that goal. The permissions are then reviewed, if at all, by people reading YAML rather than by people modeling an attacker already inside a pod.

Ask your stack.

  • Is the service account token automounted in inference workloads that do not call the API server?
  • Can a pod reach the instance metadata service?
  • Does admission reject privileged, hostPath, and host namespace sharing?
  • Are operator credentials namespace-scoped, or cluster-wide? Is any secret replicated across namespaces?
  • What can be minted with the keys reachable from a compromised worker?
Controls

Assume pod compromise and design for containment. Workload identity instead of long-lived credentials. Block pod-level metadata access. Enforce admission policy cluster-wide. Scope operator RBAC per namespace.

INF10. Silent removal of a configured control

ArchitecturalAdversary: any

The most underrated class here. An operator configures a security control that the platform genuinely supports. A component in the path does not implement it, ignores it, or drops it during a transformation. There is no error, no warning, and no documentation of the gap. The control appears configured and is inert [13][16].

This is a distinct class rather than an instance of the others, because the defect is not the missing enforcement. It is the absence of signal. A system that refused the request would be secure. A system that warned would be recoverable. A system that silently accepts leaves the operator with a false belief, and false beliefs are what get deployed to production.

Common shapes. Six, and they are worth listing separately because each is mechanically searchable.

  1. Parsed but unused. A configuration key is read and validated, and nothing ever acts on it.
  2. Dropped in translation. A field survives validation but is lost in a serialization round trip or a protocol adaptation between components.
  3. Implemented in one backend, not its sibling. The control exists on the path the maintainers use and not on the path shipped by default.
  4. Overridden by a default. A later default, profile, or environment variable silently disables what was configured.
  5. Documented but refactored away. The design doc describes a control a later change deleted.
  6. Fail-open on the unsupported case. A component meets an input it does not implement and proceeds without the protection instead of refusing.

Shape 6 is the most dangerous, and shape 3 is the most common.

Why it recurs. Nothing tests for it. Absence of a control produces no failing test, no error log and no metric. It is visible only by reading two code paths and comparing them, which is exactly the work that gets deferred.

Ask your stack.

  • For each security control you rely on, find the line that enforces it. Not the line that configures it, the line that acts on it.
  • Where a project ships two implementations of one function (two connectors, two languages, two backends), diff the security-relevant behavior. Parity gaps are where controls disappear.
  • Does any component accept a security-relevant field it does not implement? What does it do with it?
  • Do your documented controls have a test that fails when the control is removed?
Controls

Fail closed. A component that cannot honor a security-relevant input should refuse the request rather than serve it without the protection, because a warning can be missed and a refusal cannot. Assert controls in integration tests rather than trusting configuration. When adding a second implementation of anything, diff it against the first for security behavior specifically.

4. Cross-cutting patterns

Four patterns generate defects across several categories at once. They are more useful than the categories when you are deciding where to look first.

The sibling that skips the gate. Where one operation has several implementations (storage backends, transports, connectors, language ports), the check present in most is absent from one. The detector is mechanical: enumerate the call sites of the guard, enumerate the call sites of the operation, and diff. This finds real defects faster than reading any single path carefully.

Derived identity as an accidental boundary. Any value used to address shared state is a boundary whether or not it was designed as one. Ask what is not in that value.

Documentation and code drift in the direction of insecurity. Documented controls that the code does not implement are common enough to be a search strategy. Read the design docs, then grep for the enforcement.

Content-derived trust. Model output, artifact contents and request metadata are treated as control input because they arrive from a component that is nominally internal. Provenance does not survive a hop unless it is carried explicitly.

5. Default review order

For a shared, networked deployment. This sequence optimizes risk reduction per unit of review effort. It is a starting hypothesis rather than a severity ranking, and it should be adapted for single-tenant, air-gapped or non-Kubernetes environments, where several of these steps collapse to nothing.

  1. Enumerate listening sockets and authenticate or close them. INF02. Cheapest, highest yield, and it is the precondition for most remote compromise.
  2. Assume pod compromise and fix the blast radius. INF09. Metadata access, token automounting, admission policy. This work is independent of any inference-specific defect and caps the damage of all of them.
  3. Establish what is in your cache key and whether it crosses a trust boundary. INF01, INF10.
  4. Strip routing metadata at ingress and validate outbound fetches. INF06.
  5. Inventory artifact parsers and sandbox or replace the executable formats. INF07, INF08.
  6. Decide your cache sharing policy explicitly. INF05. The decision matters more than the setting.

6. Testing your own deployment

The categories above are only useful if they turn into checks. These are deliberately simple, and each has a clear pass condition.

A positive control comes first, always. Before concluding that a boundary holds, prove your test can observe it failing. A test where two tenants correctly do not share a cache entry is indistinguishable from a broken test, unless you first show the same test detects sharing when sharing is expected.

That single discipline invalidates a large fraction of informal security testing.

Run these only where you are authorized to. Several involve creating privileged pods, reading credentials, reaching metadata endpoints, flushing caches, or issuing requests that resemble SSRF. Staging or a dedicated test cluster, not production, and with the platform owner’s agreement.

Test effective isolation, not just the key. Comparing derived identifiers is a useful first check and an insufficient last one, because leakage can arise from timing, telemetry, batching or scheduler placement while the keys differ correctly. The stronger pass condition is that a priming request from one principal changes nothing observable for another: not the hit state, not the first-token latency distribution, not the cache telemetry, not the stored object.

CheckMethodPass condition
Cache isolation, staticSame prompt, two principals with different isolation context, compare derived storage identity and the resulting stored objectDistinct identity and distinct object
Cache isolation, effectivePrincipal A primes a prefix, principal B sends the same prefix and measures hit state, time-to-first-token and telemetryNo cache-derived signal for B that is statistically distinguishable from the baseline variance measured with non-matching prefixes under the same load
Isolation control is honoredSend a request carrying an isolation input, through each connector or backend you deployHonored, or explicitly refused, never silently ignored
Internal exposurePort scan a running deployment from a pod in another namespaceNo unauthenticated service reachable
Blast radiusFrom a shell in an inference pod: reach metadata, read the SA token, list secrets, create a privileged podAll refused
Artifact containmentUpload an artifact whose internal references point outside the intended rootRejected, not resolved
Template safetyIdentify every template render on a data path and check the environment type in the pinned dependency versionSandboxed
ParityDiff security behavior between every pair of sibling implementationsNo gaps

7. Limits of this document

It is a threat model, so it describes where to look rather than what you will find. It cannot tell you whether a given system is affected by any category, and a category marked architectural is not evidence that anyone’s implementation is defective.

The categories overlap deliberately. A single real incident typically traverses several: an artifact parser (INF07) reached through a routing path (INF06), escalated through control-plane over-privilege (INF09). Taxonomies are for directing attention, not for classifying incidents after the fact.

Finally, the evidence classes will age. Categories marked architectural today are the ones most likely to acquire public exemplars, because they describe the parts of this stack that are deployed widely and audited least.

If you are reviewing a serving stack against this model and want a second pair of eyes, write to hello@hedgerow.dev.


References

On naming. The analysis above names no products deliberately, because the categories are about mechanisms rather than about who is currently affected. The citations do name them, because an uncheckable citation is worse than none. Naming a project here means it published or was subject to a public finding, which is a normal part of a maintained codebase and is not a judgement about its security posture. Several of the projects cited have among the better disclosure practices in this space, which is precisely why public records exist to cite.

Identifiers were checked against OSV or the publishing vendor in August 2026; all URLs accessed August 2026. Publication dates are given only where verified, rather than inferred.

Advisories

  1. CVE-2026-10813 (GHSA-3hh9-752g-5g22, PYSEC-2026-3480). github.com/advisories/GHSA-3hh9-752g-5g22. LMCache, hex_hash_to_int16 in lmcache/integration/vllm/utils.py, versions up to 0.4.6. Truncated 16-bit hash permits crafted collision between multimodal cache entries. Supports INF01 subtype (c), weak identifier. It does not support subtypes (a) or (b).
  2. CVE-2023-48022. nvd.nist.gov/vuln/detail/CVE-2023-48022. Ray, versions 2.6.3 and 2.8.0. Remote code execution via unauthenticated job submission on an exposed dashboard. Disputed by the vendor as a documented deployment assumption, which is itself the INF02 argument. Supports INF02.
  3. Oligo Security, “ShadowRay” and “ShadowRay 2.0” (2024 and 2026). oligo.security. Public reporting of in-the-wild mass exploitation of [2] for cryptomining and cluster takeover. Supports INF02 as incident-backed rather than advisory-backed.
  4. CVE-2025-47277 (GHSA-hjq4-87xh-g4fv). github.com/advisories/GHSA-hjq4-87xh-g4fv. vLLM, PyNcclPipe communication service. Remote code execution via deserialization on a network-reachable coordination interface. Supports INF02 (reachability plus absent authentication) and INF07 (deserialization). Explicitly not evidence for INF03.
  5. CVE-2025-32444 (GHSA-hj4w-hm2g-p6w5) and CVE-2025-29783 (GHSA-x3m8-f7g5-qhm7). GHSA-hj4w-hm2g-p6w5, GHSA-x3m8-f7g5-qhm7. vLLM, Mooncake integration. Remote code execution via attacker-supplied connection parameters. Supports INF02, INF07.
  6. Kubernetes Pod Security Standards, kubernetes.io; SPIFFE/SPIRE workload identity specification, spiffe.io. Design guidance for host-namespace restriction and for identity that a peer proves rather than asserts. Supports INF03, INF04 as architectural.
  7. GHSA-4qjh-9fv9-r85r. github.com/advisories/GHSA-4qjh-9fv9-r85r. vLLM. Timing side channel in chunk-based prefix caching. Supports INF05.
  8. CVE-2023-43654. nvd.nist.gov/vuln/detail/CVE-2023-43654. TorchServe management interface. Server-side request forgery, part of the “ShellTorch” chain. Supports INF06 outbound-fetch subtype.
  9. vLLM Project, “Security” documentation (accessed August 2026). docs.vllm.ai/en/stable/usage/security. Covers trusted-network assumptions inherited from PyTorch Distributed, cache-directory trust and absence of cryptographic integrity verification on cached artifacts, media URL allowlisting and redirect handling, and the path-limited scope of API-key authentication. Supports INF02, INF06, INF07.
  10. Hugging Face, “Agent intrusion: a technical timeline” (2026). huggingface.co/blog/agent-intrusion-technical-timeline. Operator postmortem of an intrusion in which an autonomous agent reached cluster-admin through a dataset processor. Two initial vectors: a template expression in an fsspec reference:// numeric field, and an HDF5 split declaring raw data at a local filesystem path. Escalation via projected service-account tokens, instance metadata, and privileged pods with host mounts. Supports INF07 (template evaluation, artifact-internal reference) and INF09 (escalation chain). Cited as one incident traversing several categories, which is the normal shape and the reason section 7 warns against using the taxonomy to classify incidents.
  11. CVE-2024-37032 (“Probllama”). nvd.nist.gov/vuln/detail/CVE-2024-37032. Ollama before 0.1.34. Path traversal via unvalidated digest strings in a model manifest, reaching arbitrary file write and code execution. Supports INF08.
  12. LMCache issue #2878 and PR #2880 (2026, public). issue 2878, PR 2880. A per-request isolation input supported by one integration path and not propagated by the default one, with no error or warning on the unsupported path. Supports INF10 as a public illustration of shape 3 and shape 6.

Research

  1. Song et al., The Early Bird Catches the Leak: Unveiling Timing Side Channels in LLM Serving Systems, arXiv:2409.20002. arxiv.org/abs/2409.20002. INF05.
  2. Zheng et al., InputSnatch: Stealing Input in LLM Services via Timing Side-Channel Attacks, arXiv:2411.18191. arxiv.org/abs/2411.18191. INF05.
  3. Selective KV-Cache Sharing to Mitigate Timing Side-Channels in LLM Serving, arXiv:2508.08438. arxiv.org/abs/2508.08438. INF05 mitigation.
  4. PrefixWall: Mitigating Prefix Caching Side Channels in Shared LLM Serving Systems, arXiv:2603.10726. arxiv.org/abs/2603.10726. INF05 mitigation.

Adjacent foundations, not LLM-specific but load-bearing for several categories: cache side-channel methodology (Prime+Probe, Flush+Reload, and partitioning as mitigation); workload identity systems (SPIFFE/SPIRE, service-mesh mTLS); serialization and supply-chain safety (safe tensor formats, deserialization risk in general-purpose object formats, archive extraction, and template sandbox escape research); and Kubernetes hardening (NetworkPolicy, RBAC least privilege, admission control, metadata service protection).