Preprint · July 2026

LeakyLMs

Leaky Language Models: Stealing Architecture and Inference Optimizations via Per-Token Timing

Sadegh Majidi (Purdue)  ·  Niloofar Mireshghallah (CMU)  ·  Kazem Taram (Purdue)

§ TL;DR

Token generation timing leaks model architecture and optimizations

Model architecture is a trade secret. So is the way a provider serves it: which optimizations run in the inference pipeline, and how they are configured.

However, the stream of generated tokens naturally includes the arrival time of every [group of] token(s). We show that those arrival times, measured through an ordinary chat interface or API, recover both kinds of secret.

The first attack recovers deployment details: which inference optimizations a provider is running, and how they are configured. We use speculative decoding as a proof of concept to demonstrate it. On Google's Gemini Flash 2.5 the attack recovers a hidden draft model with a 128K context window. Flash 2.5 Lite matches it, and Flash 1.5 comes in at 32K. None of this is documented anywhere.

The second attack recovers the architecture itself: how deep the model is, how wide, and how many attention heads it has. The reasoning is that those choices impact how much arithmetic each generated token costs, and arithmetic costs time. We derive that relationship for a transformer running on a GPU, calibrate its constants against measurements we collect ourselves, and end up with a predictor that turns any candidate architecture into the timing curve it would produce. Recovering an unknown model then becomes a search: enumerate the plausible configurations, predict a curve for each, and keep the ones that match what was measured. We ran this against a Llama 3.1 8B model hosted on Weights & Biases' inference service and treated as a black box, and the correct hidden dimension came back ranked first.

§ Background

What's actually being streamed

A hosted model does not give you a complete response all at once. It gives you one or a few tokens, then more, and the interval between them is proportional to how long the GPU took to produce them. Providers work to keep those intervals short, because users don't want to wait. A pipeline tuned that carefully ends up publishing a high-resolution trace of its own behavior to anyone willing to timestamp the arrivals.

What sets the size of an interval? Some of it is the network. The rest is the model and the machine under it: how many matrix multiplications one forward pass needs, how big each one is, how much memory traffic they generate, and which optimizations the provider is running underneath.

Those quantities are not arbitrary. For a decoder-only transformer, nearly all of the per-token cost is set by five numbers:

  • H is the hidden dimension, the width of the vector carried through the network.
  • L is the number of decoder layers, the depth.
  • A is the number of attention heads.
  • I is the intermediate size of the MLP.
  • T is the sequence length.

The first four are the architecture, and providers treat them as confidential. The fifth is the prompt, and it belongs to the attacker. That asymmetry is what the attack exploits: sweep T across a wide range, watch how per-token latency responds, and work backwards to the four numbers you cannot see.

Diagram of a decoder-only transformer: an embedding block, a stack of L repeated decoder blocks each containing attention, MLP and normalization subcomponents, and an output projection block. Matrix dimensions on each component are annotated with the parameters H, L, A, I and T.
The five parameters that determine per-token cost. A decoder-only transformer, with the parameters that determine per-token cost marked on the components they control. H sets the width of every projection. L sets how many times the block repeats. A splits attention into heads. I sets how far the MLP expands before projecting back. T is the sequence length, the only one of the five the user gets to choose.

Network latency is the obvious objection, and it is smaller than it looks. A constant round-trip time shifts every arrival by the same amount, which leaves the differences between consecutive tokens untouched. Only the variance matters. Over the endpoints we measured it is small: mean RTT of 26.65 ms to Gemini with a standard deviation of 0.07 ms. Standard deviation sits under 5% of the fastest per-token generation time we recorded. The signal survives the network.

§ Threat model

The attacker in this work is a customer

They open an account, send prompts through the documented streaming endpoint, and record when each token arrives. That is the whole apparatus. No logits, no activations, no server logs, no privileged position on the network, no access to the machine. They know what the provider's documentation tells everyone: the model's name, its family, its advertised context length. Nothing more about what runs underneath.

The attacker has

  • A standard API account with streaming enabled
  • A timer
  • Public documentation: model name, family, advertised context length
  • Control over the content and length of their own prompts

The attacker does not have

  • Logits, logprobs, or activations
  • Server logs or system-level access
  • Any privileged network position
  • Control over generation parameters beyond what the API exposes

What they're after: the number of decoder layers (L), hidden dimension (H), attention heads (A), and MLP intermediate size (I), plus which inference optimizations are running and how they are configured.

Both attacks work from exactly this position. They differ in what they extract, not in what they are allowed to see: the same stream, the same timer.

Recovering the architecture needs one thing more. Predicting how long a candidate configuration would take requires a model of the hardware it would run on, so there we also assume the attacker knows the GPU class serving the target and can obtain the same class to calibrate against, and that the model is served from a single GPU for now. We leave Multi-GPU serving, which is how the largest frontier models actually run, to future work.

That one assumption is why the architecture results come from small and mid-size models on known hardware. The Gemini results that follow need nothing beyond the interface and a timer.

§ Attack 1

Detecting inference optimizations

Serving a model at scale is not just a matter of running it. Providers serve it through a pipeline of optimizations chosen to cut latency and cost: caching, batching, quantization, scheduling, speculation. Any optimization that makes some tokens cheaper changes how long those tokens take, and anyone timing the stream can see this dependency. In principle an attacker can probe for any of them. We demonstrate the idea with an attack on speculative decoding.1

The optimization is simple and it works. Run a small draft model ahead of the large one. The draft proposes several tokens. The large model verifies them all in a single forward pass. If the draft guessed right, several tokens are accepted at once and the expensive model ran once instead of four times. If it guessed wrong, the speculated tokens are discarded and the pipeline falls back to producing a single token the slow way, plus the wasted draft work.

Processor designers have been here before. This is speculative execution, and part of why Spectre2 worked is that speculation which gets rolled back still leaves a trace. Speculative decoding does not make every token faster. It makes the common case faster and the uncommon case slower. That difference is visible from outside the API.

Making the draft model fail on purpose

Detecting some optimization is easy. Any input-dependent variation in per-token latency tells you something is running. Attributing that variation to speculative decoding specifically is the hard part.

The lever is the draft model's context window. A draft model is picked to be small and fast, and extending its context costs both compute and memory, so in practice it gets a shorter window than the model it serves. That gives us a prompt length at which the draft goes blind and the main model does not. Past it, the draft is guessing at information it cannot read, so every speculation is rejected, not occasionally but every time.

The prompt puts a random number at the very front and pushes it back with padding:

We have a {n} digit number NUM={rand_num}. {padding}
The value of number NUM at the start was equal to

The task never gets harder. It is the same recall task at every length, so prompt length is the only thing that varies. Two details matter beyond that. The number and the padding are freshly randomized on every trial, which stops server-side caching from answering for us. And prompt lengths are sent in randomized order, so a provider that throttles by length or request sequence cannot be mistaken for a cliff.

Checking the instrument first

Before pointing this at a production API, we pointed it at a system where we already knew the answer. Llama 2 13B as the main model, TinyLlama 1.1B as the draft, running a public implementation of speculative decoding on a local GPU.

Sweeping prompt length from 82 to about 4,000 tokens, per-token latency is flat and low, and then it jumps. Binary search puts the jump at Tbreak = 2,030 tokens. Subtracting the prologue leaves 2,018. Round to the nearest power of two, since context windows essentially always are one, and the estimate is 2,048.

TinyLlama 1.1B has a 2,048-token context window. Turning speculative decoding off removes the jump entirely, which rules out the obvious alternative explanation.

Ground truth. Local speculative decoding, Llama 2 13B main + TinyLlama 1.1B draft. Per-token latency is flat until the prompt outgrows the draft model's window, then steps up and stays there. Binary search locates the step at 2,030 tokens. Minus the prologue that is 2,018, which rounds to 2,048, TinyLlama's actual context length. The point of this experiment is not the number but that we knew it in advance.

The same procedure against Gemini

Unmodified, against Google's public API. Gemini Flash 2.5 shows the cliff at a prompt length of 131,059 tokens. Below it, tokens arrive in 1.7 to 3.6 milliseconds. Above it, 8.0 to 11.2. Averaged across the four output positions we tracked, crossing the break multiplies per-token latency by 3.2×. Subtract the 17-token prologue and the draft model's context window is 131,042 tokens, or 128K less a 30-token margin.

Flash 2.5 Lite breaks at the same place. Flash 1.5 breaks at 32,743, which is 32K. Google documents none of this.

Two models, two draft windows. Gemini Flash 2.5 (left) and Flash 1.5 (right). Each trace is one output token position. The step is the point where the draft model can no longer see the number it is being asked to recall. Flash 2.5 steps at 131,059 tokens, Flash 1.5 at 32,743, which are 128K and 32K once the prologue is subtracted.
Recovered draft-model context windows. The local row is the validation case, where the ground truth was known in advance.
SystemMeasured breakRecovered draft context
Llama 2 13B + TinyLlama 1.1B (local)2,0182K ✓
Gemini Flash 2.5131,042128K
Gemini Flash 2.5 Lite131,042128K
Gemini Flash 1.532,74332K
Explore the measurements
Prompt
130,939 tokens
Measured
Regime
Last fast measurement 130,939 · first slow measurement 131,189 · break located at Tbreak = 131,059
131,059 − 17 (prologue) = 131,042 ≈ 128K , the draft model's context window.

What the test cannot see

The test detects a draft model whose context window is shorter than the main model's. A provider running a draft model with a matched window would be invisible to it, as would a deployment that speculates in some other way. This method produces false negatives by construction. Where we saw no step, "we did not detect it" is the strongest claim available.

§ Attack 2

Reading architecture off the timings

In a basic transformer, per-token generation time grows with sequence length, roughly quadratically, because attention is quadratic in T.

Write that growth as a quadratic in T and it has three coefficients: one multiplying T², one multiplying T, and a constant. Those coefficients are not free parameters. Each one traces back to a particular matrix multiplication inside the model, and the size of that multiplication is fixed by the architecture. Adding layers scales some terms and leaves others alone. Widening the hidden dimension scales a different set again. So the four numbers we are after, H, L, A and I, determine the three coefficients, and the coefficients determine the shape of the curve. Two models with different architectures produce differently-shaped curves, and the shape is a fingerprint.

Different architectures produce different curves. Predicted (solid) against measured (dashed) per-token time for eight (L, H) configurations under eager attention. Notice L=28, H=1152 and L=16, H=2048: the deeper, narrower model starts cheaper and grows faster, and the two curves cross. That crossing is what makes the configurations separable from timing alone. A single measurement at one sequence length would confuse them, a sweep does not.

A timing model you can read

We build the predictor bottom-up. Decompose a decoder block into its subcomponents, then each subcomponent into primitive operations: matrix multiplications, softmax, elementwise adds. Derive each primitive's compute and memory cost analytically as a function of T, H, A, I and the element width. Convert cost to time by dividing by the machine's peak arithmetic throughput and memory bandwidth. Then attach a coefficient to every term to absorb what the analysis does not capture: tiling, vectorization, kernel launch overhead, imperfect overlap between compute and memory.

For a single query projection that gives:

tQ-proj  ≈  α · TH²/d  +  β · (bTH + bH²)/c  +  C

α, β and C come from regression on real measurements. Fit one model per subcomponent, sum them, and add a final regression for the residual overhead that belongs to no component in particular: kernel launches, synchronization, per-iteration costs.

Why linear regression, when a neural network would fit the data better? Because the terms correspond to real cost components, so a bad fit is diagnosable. Because linear models do not chase residual noise, which a more flexible model would absorb and then fail to extrapolate from. And because individual terms can be swapped when the implementation changes, which is exactly what happens next.

Four predictors

  • EagerBaseline. Attention decomposed into cuBLAS matrix multiplications, as in a stock HuggingFace transformers forward pass.
  • Eager (Corrected)Same, plus the cuBLAS kernel corrector below. This is the variant that survives contact with architectures it has not seen.
  • Flash2Attention terms replaced with FlashAttention2's3 memory-access behavior. Derived from the algorithm, not from one implementation. Every other subcomponent is unchanged and simply refit.
  • KV-Flash2Flash2 split into a prefill formulation and a decode formulation, because KV caching makes those two phases scale differently.
Workflow diagram. The offline phase instruments reference model implementations, collects per-component timing data, derives analytical scaling terms and fits regression coefficients. That feeds an online phase which searches candidate architecture configurations against an observed timing trace.
Offline, then online. The offline phase instruments open models, collects per-subcomponent timings across many (H, L) variants, and fits coefficients to analytically-derived scaling terms. The online phase treats the resulting predictor as an oracle: synthesize a timing trace for each candidate architecture and rank candidates by distance to the trace actually observed. Only the online phase touches the target.

Modeling the library

cuBLAS does not have one matrix-multiply kernel. It has many, and it chooses between them based on operand shapes and internal heuristics. A predictor whose coefficients were fit at one set of dimensions mispredicts at another, not because the asymptotics changed but because the library quietly switched to a different kernel with different constants.

So we model the library too. A LightGBM4 classifier predicts which kernel cuBLAS will select for a given pair of operand shapes, and a small random forest per kernel predicts that kernel's runtime.

On test architectures the predictor had never seen, this takes NRMSE from 0.411 to 0.119. The naive variant fits its training family fine and falls apart off it. The corrected variant holds.

Diagram of the runtime correction pipeline. A candidate configuration of H, L, A, I and T feeds a linear regression model and a table of the model's matrix-multiply dimensions. Those dimensions are matched against a database of training samples to find the closest matmul shapes. A LightGBM cuBLAS kernel selector predicts a kernel ID for both the candidate and the closest training sample, a random-forest runtime predictor estimates each kernel's runtime, and a share-based scaling step combines them into a corrected runtime.
Correcting for the library, not the model. For a candidate configuration, every matrix multiply the architecture would issue is looked up against the closest shapes seen during training. A LightGBM classifier predicts which cuBLAS kernel each shape selects, per-kernel random forests predict their runtimes, and the ratio between them rescales the linear model's estimate. The worked example shows a candidate matmul at 0.31 ms against its nearest training sample at 0.09 ms, the gap this stage exists to close.
Under the hood: the search space

A grid over every integer configuration would be hopeless, so the space is pruned with conventions real models follow. Layer counts are integers in a plausible band. Hidden dimensions are multiples of a base stride, 64 or 128. Head count is constrained so per-head dimension divides the hidden size evenly. Combinations that no one builds, like a very deep model with a tiny hidden size, are dropped.

That leaves 1,540 candidate configurations for the main evaluation, scored against each of 130 target configurations. The whole search takes about 20 minutes across 40 CPU cores. Candidates are ranked by RMSE between their synthesized trace and the observed one, and we keep a shortlist rather than the single best match, because timing is noisy and nearby configurations can look alike under a limited set of prompts.

A retrieval counts as correct only if every targeted parameter lands within one step of the truth: one layer for L, 128 for H, 4 for A, 1024 for I.

Results

Recovering one parameter with the others fixed works well across all three implementations. Recovering both at once is markedly harder, and the reason is visible in the model: most terms depend on the product H·L, so the classifier has to separate effects the physics has already mixed.

Top-5 accuracy (%) on held-out test architectures. A hit requires every targeted parameter within one step of ground truth.
TargetEager (Corrected)Flash2KV-Flash2
Layers (L)86.1597.6983.78
Hidden dim (H)71.54100.0070.95
Both (H, L)65.3854.6245.27

The predictor also transfers across model families it was never trained on. Trained on Llama 3.2 1B alone, it predicts Qwen2.5 1.5B, Phi-3.5-mini 3.8B and Gemma2 2B with NRMSE between 0.159 and 0.186, comparable to its error on the family it learned from.

Cross-family generalization. One predictor, Eager (Corrected), trained on Llama 3.2 1B and evaluated on families it never saw.
Test modelNRMSELH(H, L)
Llama 3.2 1B0.221100.0093.6490.91
Llama 3.2 3B0.11986.1571.5465.38
Qwen2.5 1.5B0.15977.27100.0050.00
Phi-3.5-mini 3.8B0.18397.5097.5080.00
Gemma2 2B0.186100.0077.5047.50

Against a real endpoint

Everything above runs on hardware we control. The last experiment does not. We pointed the attack at Weights & Biases' Llama 3.1 8B Instruct streaming API. That is a machine we have no access to, an inference stack we did not choose and did not instrument, timed by the same client we used for the Gemini experiments.

With L fixed, the correct hidden dimension ranks first. With H fixed, the correct layer count ranks fourth. Searching both at once across 2,068 configurations, a near-match at (H=4096, L=34) ranks 8th and the true configuration (H=4096, L=32) ranks 28th.

A predictor fitted on our hardware, applied to an endpoint we do not control. Predicted against measured prefill time for W&B's Llama 3.1 8B Instruct endpoint. The curves track across the full sequence range, with the predictor running slightly low through the middle. This is the prefill stage, which carries far more architectural signal than decoding does once a KV cache is warm.

Limitations

The W&B result deserves an honest reading. It is a model from a family the predictor was trained on, though at dimensions outside its training range, served in FP16 on hardware whose class we knew. It shows the pipeline survives contact with a real API. It does not show that a frontier model is currently recoverable at this stage.

Three limits are worth stating plainly. Recovering H and L jointly drops to 45–65% even in the top five. The Flash2 and KV-Flash2 predictors are less accurate than the eager one. FlashAttention2's kernel is fused and its behavior depends on more than the dominant memory term we model, and that error propagates straight into ranking accuracy. And once a KV cache is warm, the decoding phase carries very little architectural signal, which is why the remote attack leans mostly on prefill.

§ Mitigations

Every mitigation trades against the latency it was meant to save

Make per-token time constant. Pad every token's generation to the worst case so latency stops depending on the architecture or on what the pipeline did. This closes the channel completely. It also means running every request at worst-case speed, which can be several times slower and deletes the reason the optimizations were deployed.

Buffer the stream. Emit tokens in fixed-size groups at fixed intervals rather than the moment each one is ready. This coarsens the channel instead of removing it, and it is adjustable, since larger groups leak less. The cost lands on time-to-first-token and on how responsive the stream feels, which is exactly the metric providers tune streaming for.

We do not have a mitigation that is free. The channel exists because inference is optimized and results are streamed as they arrive. Both are deliberate product decisions, and the defenses trade directly against them.

§ Responsible disclosure

Disclosure

  • 2025-11-07Speculative decoding attack and the Gemini findings disclosed to Google.
  • 2026-01-29Google acknowledged the findings.

This page describes what we found and why it matters. It is not a how-to, and it adds no operational detail beyond what the paper reports.

§ References

References

Works cited above, as they appear in the paper's bibliography. The full reference list is in the paper.

  1. Y. Leviathan, M. Kalman, and Y. Matias. Fast inference from transformers via speculative decoding. Proceedings of the 40th International Conference on Machine Learning (ICML'23), 2023.
  2. P. Kocher, J. Horn, A. Fogh, D. Genkin, D. Gruss, W. Haas, M. Hamburg, M. Lipp, S. Mangard, T. Prescher, M. Schwarz, and Y. Yarom. Spectre attacks: exploiting speculative execution. 40th IEEE Symposium on Security and Privacy (S&P'19), 2019.
  3. T. Dao. FlashAttention-2: faster attention with better parallelism and work partitioning. arXiv:2307.08691, 2023.
  4. G. Ke, Q. Meng, T. Finley, T. Wang, W. Chen, W. Ma, Q. Ye, and T.-Y. Liu. LightGBM: a highly efficient gradient boosting decision tree. Proceedings of the 31st International Conference on Neural Information Processing Systems (NIPS'17), pages 3149–3157, 2017.

§ Citation

Cite this work

@article{majidi2026leakylms,
  title   = {Leaky Language Models: Stealing Architecture and Inference
             Optimizations via Per-Token Timing},
  author  = {Majidi, Sadegh and Mireshghallah, Niloofar and Taram, Kazem},
  journal = {arXiv preprint arXiv:2607.20723},
  year    = {2026}
}

Code, measurement scripts and analysis notebooks are in the artifact repository, organized to mirror the structure of the paper.

§ Acknowledgments

Acknowledgments

This blog post was generated from our article, with a lot of help from Claude.

Supported by Longview Philanthropy. Correspondence to mmajidiy@purdue.edu.