{
  "schema_version": "1.3.0",
  "slug": "why-does-an-instance-taint-survive-tool-re-instantiation-but-not-agent-handoff-the-sandbox-provenance-split-in-untrusted-content-ingestion",
  "title": "Why does an instance taint survive tool re-instantiation but not agent handoff: the sandbox-provenance split in untrusted content ingestion",
  "date_of_record": "2026 November 13",
  "scope": "Applies to agent runtimes that propagate taint labels across tool invocations where the tool object (sandbox) is rebuilt, pooled, or serialized between steps, and where an agent-to-subagent handoff occurs. Does not apply to single-process runtimes that hold a single long-lived tool registry with in-memory taint maps and no handoff boundary.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/why-does-an-instance-taint-survive-tool-re-instantiation-but-not-agent-handoff-the-sandbox-provenance-split-in-untrusted-content-ingestion.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/why-does-an-instance-taint-survive-tool-re-instantiation-but-not-agent-handoff-the-sandbox-provenance-split-in-untrusted-content-ingestion.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/why-does-an-instance-taint-survive-tool-re-instantiation-but-not-agent-handoff-the-sandbox-provenance-split-in-untrusted-content-ingestion.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1248,
    "python_slice_tokens": 163,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "There are two independent carriers of taint: the *data provenance label* attached to the payload (a property of the bytes), and the *sandbox capability* that governs what a tool may do with tainted input (a property of the executing environment). Most implementations assume these are coupled: if a tool receives tainted bytes, the tool is \"tainted.\" The failu...",
    "what_was_observed": "A document-ingestion agent fetched an external HTML page, passed it to a `parse_html` tool, and the tool returned extracted text. The taint label (`source=external:untrusted`) was attached to the returned payload. The agent then called a `shell` tool to run a formatter over the text. The runtime's tool pool had been drained and rebuilt between steps due to a memory-pressure eviction, so the `shell` tool was a fresh i...",
    "condition_of_validity": "The invariant \"tainted payload implies restricted capability\" holds only when the taint label and the capability profile are bound to the *same lease token* and that token is validated at the point of tool execution, not at the point of tool construction or payload serialization. Concretely: the check must occur after the tool instance is leased and after th...",
    "decision_boundary": "Do not treat \"payload is labeled\" or \"tool is restricted\" as sufficient. The decision to permit execution must require the conjunction, evaluated atomically at the execution boundary: - If the tool instance was leased from a pool, re-apply the capability profile at lease time and refuse execution if the profile's taint requirement does not match the payload'...",
    "operational_effect": "After binding both halves to a lease token validated at execution, the two drift cases collapse into a single detectable error: a lease whose payload label and capability profile disagree. The runtime now raises on that disagreement rather than silently executing. The cost is one additional validation per tool call and the requirement that the handoff serial..."
  },
  "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": "c0b7961d8b661946a3872e58321e84328d08490a25889b67b95b434789aeb909",
    "verified_classes": [
      "TaintProvenanceSplitError",
      "LeaseToken"
    ],
    "verified_functions": [
      "validate_lease",
      "lease_tool"
    ],
    "verified_functions_count": 2,
    "defensive_guards_count": 2,
    "raised_exceptions": [
      "TaintProvenanceSplitError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses",
      "hashlib",
      "typing"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
