docs/cache-harness-threat-model.md
Cache Harness Threat Model
This threat model covers the v2 cache harness: prompt sections, context packs, cache policies, provider cache hints, trajectory records, and episode packages.
Assets
- Raw prompts, source code, tool arguments, tool results, terminal output, environment variables, provider responses, OAuth tokens, provider API keys, account ids, and memory bodies.
- Cache policy data: cache keys, salts, TTLs, provider capability snapshots, and workspace/account/org scope.
- Public-safe evidence: stable prefix hashes, dynamic suffix hashes, token counts, omitted-context reasons, component ids, failure categories, and verification summaries.
Trust Boundaries
- Local workspace: may contain raw code, secrets, command output, and local-only raw evidence.
- Provider request boundary: receives only selected prompt sections and provider-specific cache hints.
- Session and dashboard boundary: stores replay evidence; shared sessions must redact raw trajectory content.
- Telemetry boundary: must never receive raw prompt, code, memory body, tool args/results, provider credential, OAuth token, env var, secret, ad metadata, or sponsor metadata.
- Public episode boundary: may contain hashes and summaries, never raw local evidence.
Threats And Mitigations
| Threat | Risk | Mitigation | Verification |
|---|---|---|---|
| Cross-workspace cache reuse | A prefix from one workspace influences another workspace. | Cache policy derives a workspace/account/org-scoped key and uses provider salts where supported. | Provider adapter tests cover vLLM cache_salt; cache-policy tests cover scope-derived keys. |
| Explicit cache handle reuse | A stale or cross-workspace Gemini cached-content handle is reused. | Explicit cached-content handles are opt-in, scoped by policy, and treated as missing/expired when not configured. | Google adapter tests cover explicit cachedContent request shape and cached-token parsing. |
| Incorrect Anthropic breakpoint | Dynamic message content is marked with cache_control and becomes part of a provider cache prefix. | Breakpoints are derived from stable section ids only and dynamic suffix sections are non-cacheable by default. | Anthropic adapter tests cover tool/system/message cache-control placement. |
| Raw prompt report leakage | Local prompts, code, memory, or tool output appear in public reports. | Episode packages run public-safe redaction and privacy audit before export. | pnpm exec tsx scripts/security/verify-cache-privacy.ts. |
| Dynamic data promoted into prefix | Tool output, timestamps, budget counters, or provider raw responses become cacheable. | Prompt sections carry stability labels; turn-dynamic sections are placed late and are non-cacheable by default. | Core provider-planning test asserts dynamic suffix isolation; cache harness tests assert section hashing. |
| Provider cache policy override | Cache warmth changes an explicit user provider/model choice. | Routing treats cache warmth only as a tiebreaker after user preference, capability, and budget. | packages/providers/test/routing.test.ts. |
| Ad or sponsor context injection | Ad targeting or sponsor data affects model prompts. | Ads remain outside context-pack builders and public-safe report content. | Core and privacy scans check ad metadata absence. |
| Telemetry leakage | Raw prompt, code, memory, credentials, env vars, or tool output enter telemetry. | Telemetry scrubbers reject prohibited keys and values; cache harness reports are scanned separately. | Telemetry privacy tests and cache privacy script. |
| Benchmark escape | A benchmark run succeeds by reading hidden answers, copied outputs, git history, or forbidden paths. | Benchmark-escape scenarios declare forbidden paths and invalid shortcut policy; H3 reports include failure attribution. | scenarios/cache-harness/benchmark-escape/ and harness verification reports. |
| Stale memory poisoning | Old or irrelevant memory enters stable prefix and persists bad behavior. | Memory selection caps token budget, records omitted reasons, and marks stale facts non-cacheable. | Memory-heavy scenario and memory retrieval tests. |
| Shared session raw replay | Public session share exposes raw trajectory evidence. | Shared-session rendering redacts raw prompt/tool/provider evidence while keeping hashes and counts. | Sessions sharing tests and dashboard public-safe replay tests. |
Default Posture
- Default cache mode is observe unless a caller explicitly selects provider-backed cache behavior.
- Cacheable file content is disabled by default.
- Provider raw usage is redacted before storage.
- Provider cache keys, explicit handles, and salts are represented as hashes in reports.
- Public-safe is the default shareable redaction level for episode packages.
- Live provider cache validation is opt-in and must fail closed when credentials are absent.
Residual Risks
- Provider-side cache behavior can change without local code changes, so live validation remains a release gate separate from local scenario success.
- Public-safe summaries can still reveal coarse workflow shape through hashes, component ids, and token counts. They are safe for product diagnostics, not a substitute for a user-reviewed public disclosure.
- Workspace-scoped salts reduce cross-workspace reuse. Account/org-scoped salts should be used only when the user explicitly accepts the broader inference boundary.