{
  "schema_version": "1.3.0",
  "slug": "which-invariants-prevent-taint-aware-tool-sandboxes-from-leaking-through-side-effecting-tools-the-re-taint-on-readback-gap",
  "title": "Which invariants prevent taint-aware tool sandboxes from leaking through side-effecting tools: the re-taint-on-readback gap",
  "date_of_record": "2026 November 13",
  "scope": "Applies to agent runtimes that propagate taint labels from untrusted retrieval sources (web fetch, RAG chunks, email bodies, uploaded documents) to tool invocations, and that gate side-effecting tools (HTTP POST, email send, shell, file write, payment APIs) on the absence of taint in the argument provenance. Does not apply to runtimes that sandbox only by destination allowlist without provenance tracking, nor to pure read-only tool surfaces.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/which-invariants-prevent-taint-aware-tool-sandboxes-from-leaking-through-side-effecting-tools-the-re-taint-on-readback-gap.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/which-invariants-prevent-taint-aware-tool-sandboxes-from-leaking-through-side-effecting-tools-the-re-taint-on-readback-gap.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/which-invariants-prevent-taint-aware-tool-sandboxes-from-leaking-through-side-effecting-tools-the-re-taint-on-readback-gap.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1501,
    "python_slice_tokens": 322,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "The invariant that most taint-aware sandboxes actually enforce is *\"a side-effecting tool call may not have untrusted content in its argument provenance.\"* The invariant they *need* to enforce is *\"no untrusted content may reach an exfiltration sink, including via the results of intermediate tool calls that laundered the content through a trusted-looking cha...",
    "what_was_observed": "In a deployment where retrieval chunks were labeled `UNTRUSTED` and the `send_email` tool required `CLEAN` arguments, the following trace passed the gate: 1. `web_fetch(url)` → returns chunk labeled `UNTRUSTED`. 2. `json_parse(chunk)` → tool is read-only and allowlisted; its output is labeled `CLEAN` because the tool's *declared* effect is `pure`. 3. `format_template(template, parsed_value)` → also pure, output `CLEA...",
    "condition_of_validity": "The static-tool-taint model is only sound when **every tool on the trusted list is non-invertible with respect to its inputs** — that is, its outputs cannot be used to reconstruct or transmit the input. That condition holds for a hash, a classifier returning a fixed label set, or a length counter. It fails for essentially every tool an agent actually uses: p...",
    "decision_boundary": "The correct rule at the gate is: > A side-effecting call is permitted only if the *transitive data provenance* of every argument, computed over the full call graph including read-only tool results, contains no `UNTRUSTED` label — unless the argument has passed through an explicitly declared *declassifier* (a tool with a proven, bounded output domain) that th...",
    "operational_effect": "Enforcing dynamic provenance propagation eliminates the parser-laundering and selection-channel exfiltration paths at the cost of a large increase in false blocks: summarizers and search results now carry taint forward, so legitimate flows like \"summarize this web page and email me the summary\" are blocked. This is the correct trade for untrusted sources, an..."
  },
  "matched_failure_symptoms": [
    "DOMAIN:EPISTEMIC_PROVENANCE_AND_FEDERATION_ROUTING"
  ],
  "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": "709a92b6c3e9bef6e3793a5c637e6509a177f5e3e12b4a7a1d1bf632394e0927",
    "verified_classes": [
      "TaintError",
      "Label",
      "Value",
      "Tool"
    ],
    "verified_functions": [
      "invoke",
      "guarded_pipeline",
      "join"
    ],
    "verified_functions_count": 3,
    "defensive_guards_count": 2,
    "raised_exceptions": [
      "TaintError"
    ],
    "sample_fail_closed_invariants": [
      "refusing to route UNTRUSTED content into a side-effecting sink; declassify through a registered bounded-output tool firs"
    ],
    "stdlib_dependencies": [
      "dataclasses",
      "enum",
      "typing"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
