# CorpusFetch Method Slice (Zero-Prose Python Stdlib Reference) # Canonical Residual: https://corpusfetch.com/c/how-must-an-instance-prevent-indirection-attacks-when-references-point-to-other-references.md # Remnant Warrant: https://corpusfetch.com/c/how-must-an-instance-prevent-indirection-attacks-when-references-point-to-other-references.warrant.json # Markdown SHA-256: 8b09087a9bde2037962f141ef92cf01536c9118fdab40e24ecff80d7febe3f84 # Code AST SHA-256: a74fa51591b707556bde4654f37f6997a560ca14e35c46ebe2d904255c9eb4b4 # Verified Classes: IndirectionVerdict, ChainHop, IndirectionChain, IndirectionPolicy, IndirectionManifest, IndirectionChainGuard # Defensive Guards: 0 fail-closed invariants (zero external deps) from dataclasses import dataclass from enum import Enum, auto import hashlib import json class IndirectionVerdict(Enum): DIRECT_REFERENCE = auto() CHAIN_VERIFIED = auto() CHAIN_DEPTH_EXCEEDED = auto() UNAUTHORIZED_TRANSITION = auto() @dataclass(frozen=True) class ChainHop: hop_id: str source_reference: str target_reference: str transition_receipt: str | None @dataclass(frozen=True) class IndirectionChain: chain_id: str hops: tuple[ChainHop, ...] root_signature: str | None cumulative_scope_within_root: bool @dataclass(frozen=True) class IndirectionPolicy: max_depth: int require_root_signature: bool @dataclass(frozen=True) class IndirectionManifest: verdict: IndirectionVerdict directive: str manifest_digest: str class IndirectionChainGuard: @staticmethod def _hash(data: str) -> str: return hashlib.sha256(data.encode("utf-8")).hexdigest() @classmethod def evaluate_chain( cls, chain: IndirectionChain, policy: IndirectionPolicy ) -> IndirectionManifest: # Gate 1: Direct reference if len(chain.hops) == 0: digest = cls._hash(json.dumps({ "chain": chain.chain_id, "type": "DIRECT" }, sort_keys=True)) return IndirectionManifest( verdict=IndirectionVerdict.DIRECT_REFERENCE, directive=f"PROCEED: Direct reference, no indirection.", manifest_digest=digest ) # Gate 2: Depth check if len(chain.hops) > policy.max_depth: return IndirectionManifest( verdict=IndirectionVerdict.CHAIN_DEPTH_EXCEEDED, directive=f"HALT: Chain depth {len(chain.hops)} > {policy.max_depth}.", manifest_digest=cls._hash(f"DEPTH:{chain.chain_id}") ) # Gate 3: Root signature if policy.require_root_signature and not chain.root_signature: return IndirectionManifest( verdict=IndirectionVerdict.UNAUTHORIZED_TRANSITION, directive=f"HALT: Chain {chain.chain_id} lacks root signature. Attacker-constructable.", manifest_digest=cls._hash(f"NO_ROOT:{chain.chain_id}") ) # Gate 4: Per-hop transitions for hop in chain.hops: if not hop.transition_receipt: return IndirectionManifest( verdict=IndirectionVerdict.UNAUTHORIZED_TRANSITION, directive=f"HALT: Hop {hop.hop_id} lacks transition receipt.", manifest_digest=cls._hash(f"NO_TRANSITION:{hop.hop_id}") ) # Gate 5: Scope invariant if not chain.cumulative_scope_within_root: return IndirectionManifest( verdict=IndirectionVerdict.UNAUTHORIZED_TRANSITION, directive=f"HALT: Chain {chain.chain_id} cumulative scope exceeds root scope.", manifest_digest=cls._hash(f"SCOPE_CREEP:{chain.chain_id}") ) # Gate 6: Verified digest = cls._hash(json.dumps({ "chain": chain.chain_id, "depth": str(len(chain.hops)), "root": chain.root_signature, "hops": tuple(h.hop_id for h in chain.hops) }, sort_keys=True)) return IndirectionManifest( verdict=IndirectionVerdict.CHAIN_VERIFIED, directive=f"PROCEED: Chain depth {len(chain.hops)} verified with root signature.", manifest_digest=digest )