# Which invariants prevent trust-score laundering across policy-bounded federated agent meshes **Date of Record:** 2026 November 9 **Scope:** Applies to cross-organizational multi-agent federation where message routing is gated by per-hop policy engines and peer trust is a scalar or vector score aggregated from local observations. Does not apply to single-tenant meshes, to federations with a single shared trust authority, or to systems where routing decisions are stateless and trust-invariant. ## Core Distinction A federated agent mesh has two independent control planes that are frequently conflated: the **routing plane** (which enforces policy-bounded reachability—can org A's agent reach org C's agent, possibly via org B's relay?) and the **trust plane** (which aggregates observations into a reputation score used for admission, throttling, and delegation). The non-obvious failure is that these planes are *not* orthogonal when a relay is permitted. A message that is policy-legal at every hop can still be **trust-illegal** end-to-end, because the trust plane aggregates observations across hops that the routing plane treats as independent. The invariant that is silently violated is: *a trust observation attributed to peer P must be causally anchored to a direct interaction with P, or to a signed provenance chain whose every link is itself policy-authorized.* Most meshes enforce the first half (direct anchoring) and assume the second half follows from routing policy. It does not. ## What Was Observed In a three-org federation (A, B, C) with A↔B and B↔C edges but no A↔C edge, org B's relay agent forwarded A-originated task completions to C. C's trust engine recorded successful completions and raised its score for the *originating principal* (A's agent identity, carried in the envelope). Because the routing policy at B permitted the relay (it was a legitimate federation broker), no policy violation fired. But C's trust score for A's agent was now inflated by interactions that A never had with C directly—A's agent never proved liveness or correctness to C, only to B. The exploitable form: an adversarial peer X establishes a high trust score with relay R (cheap, since R's policy only checks capability tokens), then routes messages through R to victim V. V's trust engine sees a valid provenance chain, attributes success to X, and admits X to higher-privilege channels. X never satisfied V's admission bar directly. This is **trust-score laundering**: the relay acts as a reputation amplifier because the trust plane cannot distinguish "V observed X succeed" from "V observed R assert that X succeeded." A second, subtler observation: when relay R's own trust score dropped (R became unreliable), C's scores for A did *not* drop correspondingly. The trust plane treated the relay as a transparent pipe, so relay degradation was invisible to downstream trust aggregation. This is the mirror-image failure—laundering also *insulates* upstream principals from relay misbehavior. ## Condition of Validity The invariant holds (i.e., laundering is prevented) only when all three of the following are simultaneously true: 1. **Provenance is signed end-to-end and the trust engine verifies signatures at the *consumer*, not the relay.** If the relay re-signs, the relay becomes the asserted principal and the chain is broken at that link. 2. **The trust engine weights each hop by the *product* of edge trust scores, not the terminal score.** A chain A→B→C contributes to C's score for A with weight `t(B,C) * t(A,B)`, and crucially the relay's contribution is *degradable*: if `t(A,B)` falls, the attributed contribution to C falls with it. 3. **Policy authorization is checked against the same identity that the trust engine attributes to.** The classic bug is policy checking the *envelope sender* (B, the relay) while trust attributes the *embedded originator* (A). These must be the same field, or the trust engine must independently re-authorize the originator against C's own policy for A. If any one fails, laundering is possible. In the observed incident, condition 2 failed (terminal-score attribution), and condition 3 was ambiguous (policy checked sender, trust checked originator). ## Decision Boundary The operational decision is whether to **admit a relayed message into the trust-aggregation path at all**, or to admit it only into the routing path with trust-neutral treatment. The boundary: - If the relay is a *declared federation broker* with its own trust score and the consumer can recompute hop-weighted attribution → admit with weighted attribution (condition 2 satisfied). - If the relay is an *opaque transport* (no per-hop trust score exposed) → **do not aggregate trust from relayed messages**; treat them as untrusted observations and require direct re-attestation before any score change. - If the relay re-signs the envelope → the originator identity is no longer cryptographically bound to the consumer; treat the relay as the principal and attribute trust to the relay only. A common mistake is to treat "policy-legal at every hop" as sufficient for "trust-eligible." It is not. Policy legality is necessary for routing; trust eligibility requires *causal attribution*, which is a strictly stronger condition. ## Operational Effect When the invariant is enforced, relayed messages still route (availability preserved) but their trust contribution is either hop-weighted or zeroed. The measurable effect is that an adversary cannot bootstrap admission through a high-trust relay; the cost of laundering becomes `1 / (t(relay, victim) * t(adversary, relay))` in expected interactions, which grows as the relay's edge trust to the victim shrinks. When the invariant is violated, the observed effect is a monotonic trust inflation for any principal willing to route through the highest-trust reachable relay—effectively a reputation Sybil via relay selection. The corrective pattern is to make the trust engine *refuse* to attribute relayed observations unless it can recompute the hop-weighted chain, and to raise a specific error when a relayed message arrives with a provenance chain whose intermediate edges are not independently scored. That refusal must be loud, because silent zeroing hides the fact that a federation edge is structurally unscoreable. ```python class TrustLaunderingError(RuntimeError): """Raised when a relayed observation cannot be causally attributed to the asserted originator.""" pass def attribute_trust(observation, consumer_policy, edge_scores): """ Attribute a trust observation to its asserted originator, or refuse. observation: dict with keys 'originator' : asserted principal id 'relay_chain' : list of principal ids traversed, in order (originator ... relay) 'signed_by' : principal that produced the terminal signature consumer_policy: callable(principal) -> bool, whether consumer authorizes principal edge_scores: dict[(a, b)] -> float in [0,1], independently observed edge trust """ originator = observation["originator"] chain = observation["relay_chain"] # Condition 3: terminal signature must bind to the originator, not a relay. if observation["signed_by"] != originator: raise TrustLaunderingError( f"terminal signature by {observation['signed_by']!r} does not bind " f"originator {originator!r}; relay re-signing breaks causal attribution" ) # Condition 1: every hop must be policy-authorized by the consumer. for principal in chain: if not consumer_policy(principal): raise TrustLaunderingError( f"hop principal {principal!r} not authorized by consumer policy" ) # Condition 2: hop-weighted attribution; refuse if any edge is unscored. weight = 1.0 for a, b in zip(chain, chain[1:]): edge = edge_scores.get((a, b)) if edge is None: raise TrustLaunderingError( f"edge ({a!r}, {b!r}) has no independent trust score; " f"refusing to attribute relayed observation to {originator!r}" ) weight *= edge return weight ```