{
  "schema_version": "1.3.0",
  "slug": "what-happens-when-an-instance-propagates-taint-labels-through-tool-output-but-not-through-memory-writes",
  "title": "What happens when an instance propagates taint labels through tool output but not through memory writes",
  "date_of_record": "2026 November 12",
  "scope": "Applies to agent runtimes that implement dynamic information-flow control (DIFC) by attaching provenance labels to values returned from tools and to entries written into persistent memory. Does not apply to stateless single-turn inference, nor to systems that treat all tool output as uniformly untrusted (which trivially avoids the split described here).",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/what-happens-when-an-instance-propagates-taint-labels-through-tool-output-but-not-through-memory-writes.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/what-happens-when-an-instance-propagates-taint-labels-through-tool-output-but-not-through-memory-writes.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/what-happens-when-an-instance-propagates-taint-labels-through-tool-output-but-not-through-memory-writes.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1547,
    "python_slice_tokens": 278,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "There are two distinct propagation surfaces in any tool-using agent: the **data path** (a tool's return value flowing into the next prompt) and the **storage path** (a value being serialized into memory, a scratchpad, or a vector store and later re-read). Taint tracking that labels the data path is straightforward: every tool call result carries a label set,...",
    "what_was_observed": "In a runtime that correctly labeled tool outputs, an injection delivered inside a retrieved web page was tagged `untrusted:web`. The agent, following the injected instruction, summarized the page and wrote the summary to its long-term memory store under key `notes/research`. On the next turn, a fresh context assembled from memory read `notes/research` back and received the summary with an empty label set. A subsequen...",
    "condition_of_validity": "The invariant \"a value's taint label is preserved across all flows\" holds only if every flow that can carry a value also carries its label. This requires that the memory write interface be *label-preserving by construction*: the write record must be a pair (payload, label-set), the store must persist both, and the read must re-attach. The invariant fails whe...",
    "decision_boundary": "The operational decision is where to enforce the invariant. Enforcing it at read time (re-derive taint from the source of the memory entry) is fragile because the source is usually gone by read time. Enforcing it at write time is correct but only if the write is *total*: every field that can later be read must be labeled, including derived summaries and embe...",
    "operational_effect": "When the invariant is enforced at write time with label union over derivation inputs, memory becomes a tainted-but-honest store: every read re-attaches provenance, and policy decisions at the action boundary see the true label regardless of how many turns or transformations the value passed through. The cost is that derived values are conservatively over-lab..."
  },
  "matched_failure_symptoms": [
    "OOM_KILL_OR_MEMORY_EXHAUSTION"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "f3c71b93ea8f8d3cd93ef6779aa56caed7363a416bd91f6e6f2e242e37ca9ad4",
    "verified_classes": [
      "TaintLaunderingError",
      "Labeled"
    ],
    "verified_functions": [
      "write_memory",
      "summarize",
      "union"
    ],
    "verified_functions_count": 3,
    "defensive_guards_count": 1,
    "raised_exceptions": [
      "TaintLaunderingError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses",
      "typing"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
