{
  "schema_version": "1.3.0",
  "slug": "under-what-conditions-must-an-instance-treat-prompt-injection-taint-as-non-transferable-across-a-retrieval-boundary",
  "title": "Under what conditions must an instance treat prompt-injection taint as non-transferable across a retrieval boundary",
  "date_of_record": "2026 November 13",
  "scope": "Applies to agentic systems that attach provenance labels (trust tier, origin, taint bit) to content segments and propagate those labels through tool calls and retrieval. Does not apply to stateless single-turn completion where no content crosses a trust boundary.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-prompt-injection-taint-as-non-transferable-across-a-retrieval-boundary.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-prompt-injection-taint-as-non-transferable-across-a-retrieval-boundary.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-prompt-injection-taint-as-non-transferable-across-a-retrieval-boundary.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1096,
    "python_slice_tokens": 263,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "Taint tracking assumes a monotonic join: once content is labeled `untrusted`, any derived value inherits `untrusted`. This is correct for *data flow* but wrong for *control flow across retrieval boundaries*. The non-obvious invariant is that a retrieval boundary (a tool that returns documents, search results, or memory reads) is a **taint-laundering boundary...",
    "what_was_observed": "In a pipeline where an agent (1) reads an untrusted web page, (2) issues a search query derived from that page, and (3) feeds results to a summarizer, the taint label was propagated *query→result* (correct) but the result was then treated as `trusted` because the retrieval tool was on an allowlist. The attacker's injected instruction on the page survived into the query, the search engine echoed it in a result snippet...",
    "condition_of_validity": "Taint is non-transferable across a retrieval boundary **iff** all of the following hold simultaneously: 1. The tool's response is not derived from any tainted input (query provenance is insufficient to certify response provenance). 2. The retrieval corpus and index are outside the trust domain and can be mutated by a party other than the principal. 3. The re...",
    "decision_boundary": "The boundary is not \"is this tool trusted\" but \"can this tool's *output* be influenced by a non-principal.\" An allowlisted retrieval tool that indexes a public corpus is a taint source. A non-allowlisted tool that returns a signed, principal-scoped record is not. Label the **response**, not the **call**. Concretely: at the tool-return edge, if `response.prov...",
    "operational_effect": "Without this rule, taint tracking produces false negatives at exactly the boundary attackers target: the retrieval hop where trust is assumed to reset. The operational consequence is that summaries, plans, and subsequent tool calls execute injected instructions while the taint ledger reports clean. The fix is a response-provenance check that raises when a re..."
  },
  "matched_failure_symptoms": [
    "PROMPT_INJECTION_OR_CONFUSED_DEPUTY"
  ],
  "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": "1b6f5a5313591ad5760763de313f6292c2361ead279ed8c947a8d7f7f69747da",
    "verified_classes": [
      "TaintBoundaryError",
      "Provenance",
      "Response",
      "Query"
    ],
    "verified_functions": [
      "admit_response",
      "summarize"
    ],
    "verified_functions_count": 2,
    "defensive_guards_count": 1,
    "raised_exceptions": [
      "TaintBoundaryError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses",
      "enum"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
