Docs / Agent Mesh Security

Agent Mesh Security

When AOS agents call each other and reach external tools, three trust boundaries appear: who you are (identity), where you connect out (egress), and who connects in (ingress). Each is guarded, and the defaults fail closed.

Trust Model

  • Identity — an Agent Card can be JWS-signed so a caller verifies who it is talking to before connecting.
  • Egress — outbound calls (A2A peers, MCP HTTP servers, JWKS fetches) pass an SSRF policy that blocks internal targets.
  • Ingress — inbound A2A is auth-gated and rate/budget/concurrency limited, and tasks are owner-scoped.

Signed Agent Cards

An Agent Card can carry a detached JWS signature over the JCS-canonicalized card. This counters card spoofing: a caller confirms the card was signed by a trusted key before sending it work.

  • Algorithms are allowlisted to ES256 (ECDSA P-256) and EdDSA (Ed25519). The none algorithm and RSA are rejected — closing JWS algorithm-confusion attacks.
  • Trusted mode (a trust anchor is supplied) proves identity. Integrity mode (verify against the card's own embedded key) only detects tampering — it is not identity, and the client surfaces which mode was used.
  • Enable signing with AOS_A2A_SIGNING_KEY; if it is set but unreadable, the server refuses to start rather than serve an unsigned card.

Key Discovery (JWKS / jku)

A signing server publishes its public key as a JWKS at /.well-known/jwks.json, and the signature header carries a jku URL pointing at it. This enables key rotation without re-pinning keys out of band.

  • The published JWKS contains public material only — the private component can never reach the wire.
  • A host allowlist is the trust gate: a card cannot point its jku at an attacker-chosen JWKS.
  • JWKS fetches require https and do not follow redirects, so an open redirect on an allowlisted host cannot pivot discovery to a hostile key.
  • Keys are matched to the signature by kid or RFC 7638 thumbprint; the document size is bounded.

Egress: SSRF Defense

Agent-initiated egress — A2A peers, MCP HTTP servers, JWKS fetches — runs through a strict outbound policy:

  • Blocks private, loopback, link-local, ULA, and CGNAT addresses and internal name suffixes unless explicitly allowlisted.
  • Blocks IPv6 spellings of internal IPv4 — IPv4-mapped, IPv4-compatible, IPv4-translated, NAT64, and 6to4 — so [64:ff9b::a9fe:a9fe] can't reach the metadata service.
  • Every redirect hop is re-validated, and sensitive headers (Authorization, Cookie, …) are stripped on cross-origin hops.
  • A resolve-time guard rejects hostnames that resolve to private addresses (a DNS-rebinding defense), and response bodies are read with a hard byte cap.
  • Plain http is allowed only to loopback or allowlisted hosts; https is preferred everywhere.

Ingress: Abuse Defense

The inbound message/send path runs a real AOS pass, so it is gated before any work begins:

  • Out-of-band auth — a bearer token (constant-time compared) is required on a publicly bound endpoint.
  • Three limits — max concurrency, requests per window, and a cost budget per window. A rejected request returns a retry hint and creates no task.
  • Per-caller fair-share — with a trusted caller header, each caller gets its own bucket behind a global backstop; caller buckets are memory-bounded against a spoofed-key flood.
  • Inbound bodies are capped (Content-Length and actual bytes), and internal exceptions are logged server-side while the caller receives only a generic message.

Task Ownership

The task store records the caller that created each task. tasks/get, tasks/cancel, and task continuation are owner-scoped — a caller can only act on its own tasks, and an id belonging to another caller reads as “not found.” This closes the cross-caller access (IDOR) that a shared task store would otherwise allow. Terminal tasks are evicted on a TTL so the store stays bounded without dropping live work under load.

Secure Defaults

Surface Default
Bind interfaceloopback (127.0.0.1)
Public bind without tokenrefused (fail closed)
Ingress limitson (4 concurrent / 60 rpm / 60 budget)
JWS algorithmsES256 + EdDSA only; none rejected
jku fetchhttps-only, no redirects, host-allowlisted
Egress to private hostsblocked unless allowlisted
Signing misconfigfail closed (no unsigned fallback)

Next Steps