# What structural signals indicate a trust-anchor chain has silently degraded to a transitive self-attestation in cross-org agent federation **Date of Record:** 2026 November 11 **Scope:** Applies to federated agent meshes where capability attestations are exchanged across organizational boundaries and validated against a pinned trust anchor set (root CA or equivalent). Does not apply to single-org deployments, nor to meshes where every attestation is re-verified end-to-end against a hardware root of trust on each hop. ## Core Distinction A trust-anchor chain is *structurally valid* when the verifier can reconstruct a path from a presented attestation to a locally pinned anchor, and each link in that path was signed by a key whose authority is independent of the party being attested. It is *operationally compromised* when the path still reconstructs and every signature still verifies, but at least one link's signing authority was itself derived from the subject of the attestation. The second condition is invisible to signature checking: the math is correct, the chain is acyclic in the graph sense, and the only defect is a semantic one — the anchor no longer anchors anything outside the attested party's own transitive closure. The non-obvious failure: federation meshes that exchange attestations *and* trust anchors in the same channel will, under churn, gradually replace pinned anchors with peer-supplied ones. Each replacement is locally justified ("peer B is authoritative for domain B"), each is individually defensible, and the aggregate result is a mesh where every org's authority traces back to another org's assertion, with no external root remaining. This is transitive self-attestation. It is not a forgery; it is a slow convergence to mutual endorsement. ## What Was Observed During a cross-org agent federation incident (three participating orgs, ~400 agents, attestation TTL of 15 minutes), the following sequence was reconstructed from federation logs: 1. Org A's anchor store contained a pinned root for Org B, propagated at onboarding. Org B rotated its signing key and published a new anchor via the federation gossip channel rather than out-of-band. 2. Org A's anchor-refresh policy accepted peer-published anchors when the publishing peer's *current* attestation validated against *any* anchor in the store. Since Org B's new anchor was signed by Org B's old key, and Org B's old anchor was pinned, the refresh succeeded. This is correct behavior in isolation. 3. Org C, which had never pinned Org B out-of-band, learned Org B's anchor transitively: C trusted A, A vouched for B, so C accepted B. C's path to B ran *through A's assertion*, and A's assertion of B's authority was itself derived from B's self-published rotation. The chain C→A→B is acyclic but the authority at the B end originates at B. 4. After two further rotation cycles, all three orgs' anchor stores contained only peer-propagated anchors. No pinned external root survived. Capability attestations continued to validate with 100% signature success for 11 days. The structural signals that distinguished this degraded state from a healthy mesh were all *metadata*, not cryptographic: - **Anchor provenance age exceeded anchor pin age.** Every anchor in the store had a `provenance_source` of `gossip` rather than `pinned` or `out_of_band`, and the oldest `pinned` entry had been garbage-collected by rotation. - **Path depth to an external root was undefined.** For each attestation, the verifier could reconstruct a path but the path terminated at a node whose authority was asserted by a node *inside* the same connected component — i.e., the trust graph had no node of in-degree zero outside the attested set. - **Attestation verification latency dropped monotonically** across the incident window (from ~40ms to ~3ms) because the verifier's path search was finding shorter and shorter chains — a symptom of the graph contracting toward mutual endorsement, not of caching. - **Cross-org attestation acceptance rate rose to 100%** and stayed there. A healthy federated mesh rejects a nonzero fraction of attestations due to clock skew, TTL expiry, and capability mismatch. A sustained 100% acceptance rate across org boundaries is a signal that the verifier is no longer discriminating. ## Condition of Validity The invariant "signature verification success implies trust-anchor authority" holds **only if** the verifier's anchor set contains at least one anchor whose provenance is independent of every party in the attestation path. Concretely: - The anchor must have been introduced out-of-band (pinned at onboarding, or via a channel not controlled by the attested org). - The anchor must not have been replaced by a peer-published rotation without a corresponding out-of-band confirmation. - The trust graph induced by the anchor set, restricted to nodes reachable from pinned anchors, must have at least one pinned node of in-degree zero that is not a member of the attested party's transitive closure. When any of these conditions fails, the mesh is in transitive self-attestation. Signature checks will continue to pass. The failure is in the *set* of anchors, not in any individual verification. ## Decision Boundary Do not treat a passing signature check as evidence of federation integrity. Treat the following as the decision boundary: - **Healthy:** For every accepted attestation, the reconstructed path terminates at a node marked `pinned` or `out_of_band`, and that node is external to the attested party's domain. Anchor refresh from gossip is permitted only when the refreshed anchor's signing key chains to a still-present pinned anchor. - **Degraded:** The path terminates at a gossip-sourced node, or the pinned-anchor count for a peer domain has dropped to zero, or the trust graph's external-root component is empty. In this state, attestations must be treated as *unverified assertions* and either rejected or downgraded to a lower capability tier pending out-of-band re-pinning. - **Indeterminate:** Anchor provenance metadata is missing or unparseable. Treat as degraded; do not default to accept. The boundary is crossed the moment the last pinned anchor for a peer domain is garbage-collected by rotation, not when an attacker acts. No attacker is required. ## Operational Effect The operational consequence of missing this boundary is that a federation mesh can run for weeks with zero cryptographic failures while its cross-org capability attestations carry no external authority. Any org that can publish a rotation for its own key — which is every org — can extend its own capability claims to the entire mesh, because no path terminates outside its transitive closure. The mesh has, in effect, become a single trust domain wearing three org labels. Mitigation is structural, not cryptographic: pin an anchor-count floor per peer domain, refuse gossip-sourced anchors when they would be the sole path to that domain, alert on sustained 100% cross-org acceptance, and treat monotonically decreasing verification latency as a contraction signal rather than a performance win. The detection logic below encodes the boundary check. ```python from dataclasses import dataclass, field from typing import Iterable class TrustAnchorDegradedError(RuntimeError): """Raised when a federation mesh has lost all external trust anchors.""" pass @dataclass class Anchor: domain: str provenance: str # "pinned" | "out_of_band" | "gossip" signed_by: str # domain whose key signed this anchor @dataclass class Attestation: subject: str path: list[str] = field(default_factory=list) # domains in verification path EXTERNAL_PROVENANCE = {"pinned", "out_of_band"} def assert_external_root(anchors: Iterable[Anchor], attested_domain: str) -> None: """ Enforce the federation invariant: at least one anchor for the attested domain must have provenance independent of the attested party's closure. Raises TrustAnchorDegradedError when the mesh has collapsed to transitive self-attestation. """ anchors = list(anchors) external = [ a for a in anchors if a.domain == attested_domain and a.provenance in EXTERNAL_PROVENANCE and a.signed_by != attested_domain ] if not external: gossip = [a for a in anchors if a.domain == attested_domain] raise TrustAnchorDegradedError( f"No external trust anchor for domain {attested_domain!r}; " f"found {len(gossip)} gossip-sourced anchor(s) — mesh is in " f"transitive self-attestation and attestations must be rejected " f"or downgraded pending out-of-band re-pinning." ) def verify_attestation(att: Attestation, anchors: list[Anchor]) -> bool: # Signature math is assumed to have passed upstream; this enforces structure. assert_external_root(anchors, att.subject) return True ```