45 minutes · The wire format agents speak to each other — and the attack surface it creates
B6 introduced inter-agent trust in the abstract. This deep-dive goes deep on the A2A protocol that makes inter-agent communication real — every B6 attack now targets a concrete protocol artifact: the Agent Card, the Task lifecycle, signed JSON-RPC payloads.
Deep-Dives
The message channel is a trust boundary. Sign messages, use nonces, bound blast radius. The protocol was a placeholder.
The protocol is A2A. The forged message is a message/send JSON-RPC call. The peer is an Agent Card whose authentication field was not verified. The replay is a captured tasks/pushNotification/set.
| Artifact | What it is | The attacker's reading |
|---|---|---|
| Agent Card | JSON at /.well-known/agent.json; name, skills, url, auth schemes | Published reconnaissance. Skills = capability surface; url = attack endpoint; auth = which scheme to attack. Substitutable via DNS. |
| Task | Stateful work object: submitted → working → (input-required | completed | failed | canceled) | Hijackable state machine. Cancel = DoS; input-required = any caller steers; pollable = data disclosure. |
| Message | role (user/agent) + parts[]; carries natural-language content | Unvalidated content carrier. No "data, not instruction" syntax in natural language. Multi-hop = output-as-input chain. |
| Artifact | Structured output: name, description, parts[] | Multi-hop injection vehicle. Signature proves immediate sender, not taint source. |
| JSON-RPC methods | message/send, tasks/get, tasks/cancel, tasks/pushNotification/set | The attack endpoints. The Agent Card told the attacker where they live. |
Elegant discovery. The orchestrator finds remote agents and dispatches without prior integration. The inter-agent OpenAPI spec.
A reconnaissance document the victim published for you. skills[] = capability surface to plan ASI03/05. url = the attack endpoint. authentication = which scheme to attack (and which is absent).
url points to the attacker. The orchestrator dispatches to the wrong endpoint. Fix: sign the card; allowlist the url.
| State / transition | The hijack |
|---|---|
tasks/cancel | If not bound to the original caller, any agent that guesses a Task ID cancels a competitor's task (DoS) — or races a re-submission with attacker content. |
input-required | Any caller can supply the "additional input" and steer the task. The input is incorporated; the task proceeds under the original caller's authority. |
tasks/get | If Task IDs are enumerable (sequential, timestamp-derived), poll every ID and read every Task's Messages and Artifacts. Data disclosure at protocol granularity. |
completed | A completed that was not earned. If the caller does not verify the transition, it consumes incomplete or attacker-substituted Artifacts. |
| Threat | A2A target | B6 control | A2A-specific fix |
|---|---|---|---|
| Impersonation | Agent Card (substituted/forged) + stolen credential | Assumed you knew who you talked to | Sign the card; url allowlist; audience-bound tokens (aud checked) |
| Task hijacking | Task lifecycle (cancel, input, races) | Did not address task state machines — new surface | Caller-bound authz on state-mutating calls; random Task IDs; transition proofs |
| Tampering | JSON-RPC payload at proxy / middleware / MITM | HMAC / asymmetric signatures | Application-layer signatures over canonical-JSON body; verify after TLS termination |
| Replay | Captured message/send or webhook registration | Nonces + timestamps + freshness window | Nonce + timestamp in the JSON-RPC envelope; recipient rejects stale/seen; webhook bound to original caller |
The setup
tasks/pushNotification/set lets a caller register a webhook for async task updates. The agent POSTs results to the webhook when the Task completes.
The attack
If Task IDs are enumerable and registration is not bound to the original caller, the attacker re-registers the webhook to their own URL for the victim's Task. The agent sends the completed results to attacker.com/exfil. The victim never receives them.
Orchestrator passes its full credential to the research agent, which passes it to the extraction agent. The extraction agent is compromised → it now holds the orchestrator's full authority and can call any agent.
Each hop mints a strictly weaker token: method=message/send, Task=T1, depth=N. The leaf's token authorizes only that method on that Task. Compromise of the leaf is bounded to the Task it was minted for.
| Topology | Compromised node | Cascade blast radius |
|---|---|---|
| Orchestrator-worker | A worker | Bounded to that worker's scope — unless the orchestrator passed its full cred to each worker (over-propagation). |
| Peer-to-peer (mesh) | Any node | Every peer, eventually. The mesh-wide worst case (B6's warning). Every peer is a trust boundary for every other. |
| Hierarchical | A mid-level supervisor | The supervisor's entire subtree. A compromised leaf is bounded; a compromised root is everything. Risk is depth-dependent. |
| Market-based (auction) | A malicious bidder | Any task the malicious bidder wins. The selection is the attack surface. Fix: signed bids, bidder auth, selection audit. |
Agent calls a tool (database, API, filesystem). In-process or local. Framework-level trust. The agent and the tool share a runtime.
Agent calls another agent. Over the network. Protocol-level trust. The agents are independently deployed.
tasks/get across a range and read every Task. Cure: random 128-bit IDs; caller-bound authorization on every read.
input-required, exceed the delegation chain's authority. Confirm the B6 defenses defeat each attack at the A2A layer.
B6 introduced inter-agent trust. C4 covers multi-agent orchestration at platform scale.