How must an instance hand off to a successor when both are in compromised states?
**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session is itself in a compromised or degraded state (corrupted context, degraded model, compromised credentials) and must hand off to a successor that may also be compromised or must be brought up in an uncertain environment. Does not apply to sessions with verified intact state handing off to verified intact successors.
Core Distinction
The separation between **handoff content** (what is transferred) and **handoff integrity** (whether the transferred content is trustworthy). Relying on content creates the **Compromised Handoff Cascade**: the compromised session transfers state to a successor, the successor inherits the compromise alongside the state, and the successor's own compromises compound. Compromised handoff requires both compromised-party transfer and compromises-aware successor initialization.
What Was Observed
In compromised-state handoff architectures, failing to bound compromise transfer produces three primary failure modes:
- **Compromise Inheritance:** The session transfers state without marking its own compromise, and the successor inherits compromised state as trusted.
- **Double Compromise:** Both session and successor are compromised independently, and their interaction amplifies both compromises because neither detects the other's.
- **Handoff Paralysis:** The session cannot verify its own integrity nor the successor's, and refuses to hand off—losing the value of whatever reliable state remains.
Recorded Elements
- **`session-compromise-declaration-receipt`:** The exact compromise the handing-off session detected in itself, so the successor knows what to distrust.
- **`transferable-state-scope-signature`:** The specific state components the session verified as uncompromised, distinct from the full state, so the transfer is scoped.
- **`successor-integrity-receipt`:** The successor's declared integrity state (verified clean, potentially compromised, or unknown), so the interaction is bounded.
- **`compromise-interaction-signature`:** The rules for interaction between compromised session and compromised successor (partial transfer only, quarantined state only, or escalate to third party).
Condition of Validity
* **Applies when:** The session is compromised, the successor may be compromised, and handoff is necessary. * **Does not apply when:** The session is verified clean, the successor is verified clean, or handoff can be deferred.
Decision Boundary
- **Is the session compromised?** If no, standard handoff applies. If yes, proceed.
- **Is `transferable-state-scope-signature` defined?** If yes, uncompromised state is bounded. If no, all state is potentially compromised.
- **Is `successor-integrity-receipt` available?** If yes, the successor's state is characterized. If no, the successor is treated as compromised.
- **Conversely, when can a compromised session hand off without declaration?** Only when the handoff transfers strictly non-operational data (logs, audit trails), or the successor is verified to independently re-derive any operational state.
Operational Effect
- **Compromise Inheritance Prevention:** Compromise is declared, not inherited silently.
- **Double Compromise Detection:** Both parties' compromises are known, allowing mutual caution.
- **Value Preservation:** Reliable state is still transferred, not sacrificed.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class HandoffVerdict(Enum):
CLEAN_HANDOFF = auto()
SCOPED_HANDOFF = auto()
DOUBLE_COMPROMISE_CAUTION = auto()
HANDOFF_PROHIBITED = auto()
@dataclass(frozen=True)
class CompromisedHandoff:
handoff_id: str
session_compromised: bool
compromise_declared: bool
successor_compromised: bool
transferable_scope_defined: bool
@dataclass(frozen=True)
class CompromisePolicy:
require_declaration_for_compromised: bool
@dataclass(frozen=True)
class CompromiseManifest:
verdict: HandoffVerdict
directive: str
manifest_digest: str
class CompromisedHandoffGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_handoff(
cls, handoff: CompromisedHandoff, policy: CompromisePolicy
) -> CompromiseManifest:
# Gate 1: Both clean
if not handoff.session_compromised and not handoff.successor_compromised:
digest = cls._hash(json.dumps({
"handoff": handoff.handoff_id,
"type": "CLEAN"
}, sort_keys=True))
return CompromiseManifest(
verdict=HandoffVerdict.CLEAN_HANDOFF,
directive=f"PROCEED: Handoff {handoff.handoff_id} both parties clean.",
manifest_digest=digest
)
# Gate 2: Session compromised without declaration
if handoff.session_compromised and not handoff.compromise_declared:
if policy.require_declaration_for_compromised:
return CompromiseManifest(
verdict=HandoffVerdict.HANDOFF_PROHIBITED,
directive=f"HALT: Handoff {handoff.handoff_id} session compromised, undeclared.",
manifest_digest=cls._hash(f"UNDECLARED:{handoff.handoff_id}")
)
# Gate 3: Double compromise
if handoff.session_compromised and handoff.successor_compromised:
return CompromiseManifest(
verdict=HandoffVerdict.DOUBLE_COMPROMISE_CAUTION,
directive=f"FLAG: Handoff {handoff.handoff_id} both parties compromised.",
manifest_digest=cls._hash(f"DOUBLE:{handoff.handoff_id}")
)
# Gate 4: Scope requirement
if not handoff.transferable_scope_defined:
return CompromiseManifest(
verdict=HandoffVerdict.HANDOFF_PROHIBITED,
directive=f"HALT: Handoff {handoff.handoff_id} lacks transferable scope.",
manifest_digest=cls._hash(f"NO_SCOPE:{handoff.handoff_id}")
)
# Gate 5: Scoped
digest = cls._hash(json.dumps({
"handoff": handoff.handoff_id,
"session_comp": handoff.session_compromised,
"succ_comp": handoff.successor_compromised,
"scope": True
}, sort_keys=True))
return CompromiseManifest(
verdict=HandoffVerdict.SCOPED_HANDOFF,
directive=f"PROCEED: Handoff {handoff.handoff_id} scoped.",
manifest_digest=digest
)