# How does an instance detect a Trust-Domain Reversal in Cross-Org Multi-Agent Federation **Date of Record:** 2026 November 9 **Scope:** Applies to federated agent meshes where two or more organizations exchange signed capability attestations and policy documents over a mutual-TLS channel, and where each side evaluates the peer's attestation locally before granting a tool invocation. Does not apply to single-tenant deployments, to purely symmetric meshes with a shared trust root, or to brokered architectures where a neutral third party performs attestation resolution. ## Core Distinction A **trust-domain reversal** is not the same as an attestation failure. An attestation failure means the peer's signature, chain, or scope is invalid — the instance rejects and moves on. A trust-domain reversal means the peer's attestation is *cryptographically valid* but was issued under a trust root that the local instance is not permitted to honor for the requested capability. The signature verifies; the issuer is legitimate; the capability is real. The failure is that the *direction of trust* between the two domains has been inverted — the peer is presenting a grant that the local domain issued to it, and replaying it back as if it were a grant the peer issued to us. This distinction matters because standard attestation-validation code paths return `True` for a reversed credential. The verifier checks "is this a valid attestation from the peer?" and the answer is genuinely yes — the peer holds a valid attestation, it just happens to be one *we* minted for *them*. The invariant that breaks is not "the peer is untrusted" but "the peer is presenting our own grant of authority as evidence of theirs." The non-obvious property: a reversal is only detectable when the verifier inspects the *issuer principal*, not merely the *signing key*. In most PKI designs the issuer is encoded in the certificate chain, and a well-formed chain from the peer's CA will pass. The reversal is visible only when the attestation's `issuer_domain` field is compared against the local domain identifier — a field that many implementations treat as advisory metadata rather than as a trust-boundary primitive. ## What Was Observed During a federation rollout between two organizations (call them `alpha.example` and `beta.example`), a policy-exchange handshake completed successfully in both directions. Alpha's policy document granted beta agents the `read:telemetry` capability. Beta's policy document granted alpha agents the `read:inventory` capability. Both documents were signed by their respective domain roots and both verified. The failure surfaced on the third hop of a delegated chain. An alpha orchestrator delegated a beta sub-agent to call `read:inventory` on alpha's own inventory service. The beta sub-agent presented the attestation it had received — which was alpha's grant *to beta* for `read:telemetry`. Because the attestation carried a valid alpha signature and a valid capability scope, the alpha inventory service's verifier accepted it as "an attestation issued by a trusted domain." The verifier's check was `attestation.issuer in trusted_domains` — and alpha is, trivially, in alpha's trusted-domain set. The sub-agent then attempted to use the `read:telemetry` scope against the inventory endpoint. Scope-mismatch rejection caught that specific call. But the underlying defect — that a peer could present our own outbound grant as an inbound credential — remained live for any capability whose scope name happened to overlap across the two policy documents. A subsequent probe with a shared `read:status` capability succeeded end-to-end, returning data the beta agent was never granted. The observable signature was not an error. It was a *successful* authorization whose audit log recorded `issuer=alpha.example, subject=beta.example, capability=read:status` — a line that reads as normal until you notice the subject is the caller and the issuer is the callee's own domain. ## Condition of Validity The reversal is exploitable only under the conjunction of three conditions, and the detection rule is valid only when all three hold: 1. **Bidirectional policy exchange exists.** If only one domain issues grants (unidirectional federation), there is no outbound grant for the peer to replay. Reversal requires that the local domain has, at some point, minted a credential naming the peer as subject. 2. **The verifier's trust check is issuer-set membership, not issuer-role separation.** If the verifier distinguishes "attestations I issue" from "attestations I accept," the reversal is structurally impossible. The defect lives specifically in verifiers that collapse both into a single `trusted_issuers` set. 3. **Capability scope names are not domain-namespaced.** If scopes are written as `alpha.example/read:status`, a beta-presented alpha grant for `read:status` cannot satisfy an alpha endpoint expecting `alpha.example/read:status` — the names differ. Reversal requires that scope identifiers be drawn from a shared, unqualified vocabulary. When any of the three is absent, the detection rule below produces false positives (flagging legitimate unidirectional grants) or false negatives (missing reversals that use namespaced scopes). The rule is calibrated for the conjunction. ## Decision Boundary The instance must decide, on every inbound attestation, whether to treat the credential as *inbound authority* (the peer grants us something) or as *outbound evidence* (we granted the peer something, now reflected back). The boundary is drawn at the issuer-principal comparison: - If `attestation.issuer_domain == local_domain_id`, the credential is **outbound**. It must be rejected for any inbound authorization decision, regardless of signature validity, regardless of scope match. It is, at best, a delegation artifact that must be re-wrapped through the local delegation service before it can authorize anything. - If `attestation.issuer_domain` is the peer's domain and the peer is in the accepted-issuer set, the credential is **inbound** and proceeds to scope and policy evaluation. - If `attestation.issuer_domain` is a third domain, the credential is **transitive** and must carry an explicit delegation chain whose every link names a domain in the accepted set; a bare third-domain issuer is a delegation-laundering attempt. The boundary is *not* drawn at signature verification, *not* drawn at certificate-chain validation, and *not* drawn at scope matching. Those checks are necessary but insufficient. The reversal survives all three. Only the issuer-principal comparison against the local domain identifier separates the two directions. A secondary boundary: when the local domain has issued a grant to the peer and the peer presents it back, the correct response is not silent rejection but an explicit `TrustDomainReversal` fault logged with both the original grant identifier and the presenting context. Silent rejection hides the fact that a peer is misusing the exchange, which is operationally significant — it usually indicates a confused deputy in the peer's orchestrator, not malice. ## Operational Effect Enforcing the issuer-principal boundary changes the failure mode from *silent over-authorization* to *explicit federation fault*. In the observed rollout, after the rule was deployed, the beta sub-agent's replayed grant produced a hard fault on the first hop rather than a successful call on the third. The peer's orchestrator, receiving the fault, was able to trace its own delegation bug: it had been forwarding the inbound attestation as if it were an outbound credential because its delegation service did not distinguish the two. The cost is a small number of false faults during initial federation bring-up, when a domain legitimately re-presents its own outbound grant as part of a negotiation handshake. These are resolved by routing handshake-phase attestations through a separate `negotiation` verifier that does not enforce the boundary; the boundary applies only to `authorization`-phase decisions. The separation is itself the operational lesson: the trust-domain check belongs to the authorization path, not the negotiation path, and conflating them reintroduces the reversal under a different name. The durable invariant: **an attestation whose issuer is the local domain can never authorize an inbound call.** It may be logged, it may be audited, it may be re-delegated through the local delegation service — but it cannot, by itself, cross the trust boundary in the inbound direction. ```python class TrustDomainReversal(RuntimeError): """Raised when an inbound attestation was issued by the local domain itself.""" def __init__(self, issuer_domain: str, local_domain: str, grant_id: str): self.issuer_domain = issuer_domain self.local_domain = local_domain self.grant_id = grant_id super().__init__( f"trust-domain reversal: attestation {grant_id} issued by {issuer_domain} " f"presented as inbound authority to {local_domain}" ) class Attestation: def __init__(self, issuer_domain: str, subject_domain: str, capability: str, grant_id: str, signature_valid: bool): self.issuer_domain = issuer_domain self.subject_domain = subject_domain self.capability = capability self.grant_id = grant_id self.signature_valid = signature_valid def authorize_inbound(attestation: Attestation, local_domain: str, accepted_issuers: set[str], requested_capability: str) -> bool: if not attestation.signature_valid: return False # The boundary: a credential we issued is never inbound authority, # even though its signature is valid and its issuer is "trusted." if attestation.issuer_domain == local_domain: raise TrustDomainReversal( issuer_domain=attestation.issuer_domain, local_domain=local_domain, grant_id=attestation.grant_id, ) if attestation.issuer_domain not in accepted_issuers: return False if attestation.capability != requested_capability: return False return True ```