# SGLang KV-cache differential probes: public evidence bundle

This bundle supports the article on the Cloudflare-disclosed KV-cache exposure incident. It publishes the two original CPU differential probe scripts, their four raw JSON outputs, the P2 receipt, and the original SHA-256 values recorded for those artifacts.

## Scope and limits

- These experiments exercise real SGLang queue/retirement code on pinned source trees, with Mock collaborators for transport/cache/scheduler boundaries.
- Environment: Linux, Python 3.12.3, pytest 9.2.0, torch 2.14.1+cpu, transformers 5.12.1; 2 vCPU / 7 GB RAM.
- No GPU, RDMA transfer, model weights, tenant data, production service, or real GLM-5.3 inference was used.
- The results do **not** reproduce a real cross-tenant leak. The incident itself is described in [Cloudflare's report](https://blog.cloudflare.com/kv-cache-exposure-remediation/); see also [SGLang PR #36988](https://github.com/sgl-project/sglang/pull/36988), [PR #38935](https://github.com/sgl-project/sglang/pull/38935), and [issue #30233](https://github.com/sgl-project/sglang/issues/30233).

## Experiments

### A — Admission-door differential for PR #38935

- Base: [17ba2c2e7c7b81f31a8a9e693e7435ab262c16b4](https://github.com/sgl-project/sglang/commit/17ba2c2e7c7b81f31a8a9e693e7435ab262c16b4)
- Head: [8f3d6944b76c428d884582cb6c82a39db1465360](https://github.com/sgl-project/sglang/commit/8f3d6944b76c428d884582cb6c82a39db1465360)
- Script: [probe_admission_differential.py](./probe_admission_differential.py)
- Raw outputs: [pre-fix](./probe-admission-pre-20261028.json) · [post-fix](./probe-admission-post-20261028.json)

Observed: before the admission guard, an intake-rejected request could enter the prefill queue and create a sender, or create a decode receiver. After the fix, those rejected requests were retired at the admission door. Valid requests and a resource-owning re-entry case remained admitted, so the guard does not simply retire every request carrying an abort marker.

### B — Aborted-prefill-result cleanup differential for PR #36988

- Base: [9c254df8cdbe99ef5f58e7fcd932da052f258538](https://github.com/sgl-project/sglang/commit/9c254df8cdbe99ef5f58e7fcd932da052f258538)
- Head: [2ee5742af92db2727236460473554c2ee8c4ddaa](https://github.com/sgl-project/sglang/commit/2ee5742af92db2727236460473554c2ee8c4ddaa)
- Script: [probe_prefill_differential.py](./probe_prefill_differential.py)
- Raw outputs: [pre-fix](./probe-prefill-pre-20261028.json) · [post-fix](./probe-prefill-post-20261028.json)

Observed: pre-fix aborted results could be cached as unfinished and requeued; a delayed result for an already-retired request could still send a KV chunk. Post-fix, the relevant paths released resources once and stopped those side effects.

The associated upstream test run was **0/7 passed before the fix and 7/7 passed after it**. The seven pre-fix failures were not seven assertion failures: six were `AttributeError` exceptions and one was a `ValueError` caused by the test stub falling through into a normal transfer path it did not model. The P2 receipt records these failure modes and the original log hashes.

## Reproduce

1. Check out the base and head commits listed for the experiment into separate source trees.
2. Create an isolated Python environment with the pinned dependencies recorded in [sglang-cpu-p2-receipt.json](./sglang-cpu-p2-receipt.json). Do not install or load model weights.
3. Run each probe once against the base tree and once against the head tree, following the invocation comment at the top of each script. Compare the emitted JSON with the corresponding pre/post artifacts above.
4. Verify the published scripts and raw JSON output files:

```sh
sha256sum -c SHA256SUMS.txt
```

The hashes are the SHA-256 values recorded in the original P2 receipt. The receipt also records the upstream tarball hashes and the original upstream-test log hashes; those environment-specific raw test logs are not included in this public bundle.

## Root-cause source excerpt

At the pinned [SGLang source commit](https://github.com/sgl-project/sglang/blob/8f3d6944b76c428d884582cb6c82a39db1465360/python/sglang/srt/managers/schedule_batch.py), `set_finish_with_abort()` stores the pending abort in `to_finish`, while `finished()` checks `finished_reason`; `update_finish_state()` performs the later transition:

- [`set_finish_with_abort()`](https://github.com/sgl-project/sglang/blob/8f3d6944b76c428d884582cb6c82a39db1465360/python/sglang/srt/managers/schedule_batch.py#L2053-L2072)
- [`finished()`](https://github.com/sgl-project/sglang/blob/8f3d6944b76c428d884582cb6c82a39db1465360/python/sglang/srt/managers/schedule_batch.py#L1479-L1481)
- [`update_finish_state()`](https://github.com/sgl-project/sglang/blob/8f3d6944b76c428d884582cb6c82a39db1465360/python/sglang/srt/managers/schedule_batch.py#L1842-L1848)

