# Why does an instance of a federated agent boundary silently downgrade trust when a policy-mediated route traverses two or more federation gateways **Date of Record:** 2026 November 13 **Scope:** Applies to cross-organizational multi-agent systems where inter-federation routing is mediated by policy engines at each org boundary and where trust level is carried as an attribute on the message envelope rather than re-derived at each hop. Does not apply to single-federation deployments, to routes that terminate within one trust domain, or to systems where the receiving gateway re-authenticates the originating principal end-to-end. ## Core Distinction There is a difference between *trust attenuation* and *trust downgrade*. Attenuation is the intended, monotone reduction of privilege as a message crosses a boundary — a capability is narrowed, an audience is reduced, an expiry is shortened. Downgrade is the pathological case where a message that should have been *rejected* at an intermediate gateway instead arrives at the destination carrying a *lower* trust level than the sender asserted, and the destination treats that lower level as sufficient because its own policy only checks a floor, not a match. The non-obvious boundary failure is this: a policy-mediated route that crosses *N* gateways can produce a final trust level that is a partial order meet of all gateways' policies. When the meet is computed by "take the minimum of asserted levels," an intermediate gateway that does not recognize the sender's trust vocabulary will substitute its own default — typically `UNTRUSTED` or `GUEST` — and that substitution propagates forward as if it were an attenuation. The destination cannot distinguish "the sender asserted `PARTNER` and an intermediate deliberately attenuated to `GUEST`" from "an intermediate did not understand `PARTNER` and defaulted to `GUEST`." Both arrive as `GUEST`, and if the destination's policy accepts `GUEST` for the requested operation, the message is admitted under a trust assumption no party actually made. ## What Was Observed In a three-org federation (A → B → C) where A asserts `trust=PARTNER_V2` on its envelope, gateway B's policy engine was configured against a trust vocabulary that predated `PARTNER_V2` and mapped unknown levels to `GUEST`. Gateway C's admission policy permitted `GUEST` to invoke a read-only tool. The result: a principal from A that B's operators had never vetted, and that B would have rejected had it recognized the level, was able to invoke a tool at C. The failure was not visible in any single gateway's logs. B logged `route: A→C, trust: GUEST, action: forward` — an entry that looks like correct attenuation. C logged `admit: trust=GUEST, tool=read`. Only a cross-gateway correlation of the *original asserted level* against the *received level* revealed the substitution. The invariant that was violated is not "trust must not increase" (it did not) but "the trust level at the destination must be in the image of a deliberate policy decision at every hop, not a default." A second observation: the downgrade is *sticky*. Once B rewrote the envelope to `GUEST`, no downstream gateway could recover the original level, because B did not preserve the asserted level in a signed, append-only provenance field. The provenance was lossy by design — each gateway rewrote `trust` in place. ## Condition of Validity The downgrade occurs if and only if all of the following hold simultaneously: 1. Trust level is carried as a mutable attribute on the envelope rather than as a signed claim in an append-only provenance chain. 2. At least one intermediate gateway's policy vocabulary does not contain the asserted level, and that gateway's default for unknown levels is a *permissive* level rather than a *reject*. 3. The destination's admission policy tests trust against a floor (`trust >= GUEST`) rather than against an allowlist of levels it expects to receive on that route. 4. The route is multi-hop; a single-hop route has no intermediate to perform the substitution. If any one condition fails, the failure does not manifest. Removing condition 2 (default to reject on unknown) is the cheapest mitigation but is operationally unpopular because it breaks federation during vocabulary rollout. Removing condition 1 (append-only signed provenance) is the correct fix but requires envelope schema change across all orgs. ## Decision Boundary The operational decision is whether to treat an unrecognized trust level at an intermediate gateway as a *reject* or as a *forward-with-default*. The boundary is determined by whether the destination policy can distinguish the two cases described in Core Distinction. - If the destination policy checks trust against a *floor* only: an intermediate MUST reject on unrecognized level. Forwarding with a permissive default is unsafe because the floor test cannot detect the substitution. - If the destination policy checks trust against an *exact allowlist per route*: an intermediate MAY forward with a default, because the destination will reject any level not explicitly expected on that route. This is the only configuration in which "forward with default" is sound. - If the envelope carries signed provenance of the asserted level alongside the effective level: the intermediate MAY forward with a default, and the destination SHOULD re-evaluate the asserted level against its own vocabulary rather than the effective level. The dangerous middle ground — floor-checking destination plus defaulting intermediate — is the configuration that produced the observed incident. It is also the most common configuration, because floor checks are easy to write and defaulting intermediates are easy to deploy. ## Operational Effect The practical consequence is that a federation's effective trust boundary is the *weakest* gateway's vocabulary, not the destination's policy. Operators who reason about trust at the destination alone will systematically overestimate the boundary. The correct mental model is that every gateway on the route is a potential trust *editor*, and the destination sees only the final edited value. Mitigations that worked in practice, in order of deployment cost: 1. Make the default for unrecognized trust levels `REJECT`, not `GUEST`. This is a one-line policy change and closes the failure immediately, at the cost of breaking routes during vocabulary rollout. 2. Add an `asserted_trust` field that is signed by the originator and never rewritten, alongside the mutable `effective_trust`. Destination policies compare the two and reject when `effective_trust` is lower than `asserted_trust` without a signed attenuation record explaining why. 3. Require that every gateway's policy engine declare its supported trust vocabulary at federation-join time, and reject routes whose asserted levels are not in the intersection of all gateways' vocabularies. This is the structural fix but requires a control plane that most federations lack. The invariant to encode in any monitoring: for every message, `effective_trust` at the destination must equal either `asserted_trust` or a value produced by a signed attenuation step. Any other value is a silent downgrade and should page. ```python from dataclasses import dataclass from enum import IntEnum class TrustLevel(IntEnum): UNTRUSTED = 0 GUEST = 1 PARTNER = 2 PARTNER_V2 = 3 class TrustDowngradeError(RuntimeError): """Raised when a federated message's effective trust is lower than the asserted trust without a signed attenuation record explaining the gap.""" @dataclass(frozen=True) class Envelope: asserted_trust: TrustLevel effective_trust: TrustLevel attenuation_record: str | None # signed proof of a deliberate step-down def admit_at_destination(env: Envelope, required_floor: TrustLevel) -> None: # Detect silent downgrade: effective < asserted with no signed reason. if env.effective_trust < env.asserted_trust and env.attenuation_record is None: raise TrustDowngradeError( f"silent trust downgrade: asserted={env.asserted_trust.name} " f"effective={env.effective_trust.name} with no attenuation record; " f"an intermediate gateway likely substituted a default for an " f"unrecognized trust level" ) if env.effective_trust < required_floor: raise TrustDowngradeError( f"trust floor not met: effective={env.effective_trust.name} " f"required={required_floor.name}" ) def route_through_gateway( env: Envelope, gateway_vocabulary: set[TrustLevel], default_on_unknown: TrustLevel, ) -> Envelope: if env.asserted_trust not in gateway_vocabulary: # The dangerous case: defaulting to a permissive level forwards a # downgrade that the destination's floor check cannot detect. if default_on_unknown > TrustLevel.UNTRUSTED: raise TrustDowngradeError( f"gateway does not recognize {env.asserted_trust.name} and " f"would default to {default_on_unknown.name}; configure " f"REJECT-on-unknown or carry signed provenance before forwarding" ) return env ```