When you connect two AI agents across a network, it is easy to assume that HTTPS and a Bearer token keep things safe. Transport encryption proves where a packet came from. It does not tell you if the caller was tricked by prompt injection, or whether they actually own the task they want to read.
Anthropic's Model Context Protocol (MCP) connects an agent to local tools. The Agent2Agent (A2A) protocol, open-sourced by Google and governed under the Linux Foundation, handles horizontal task delegation between independent remote agents Google A2A announcement.
While OWASP published the OWASP Top 10 for Agentic Applications 2026 OWASP Agentic Top 10, there is no official OWASP list specifically for A2A. Recent research from Purdue and UT Dallas in A2ABreak A2ABreak paper and real SDK bug fixes reveal ten common risks developers face.
Here is what goes wrong and what to check during code review.
1. Agent Card Context Poisoning
An A2A server advertises its abilities in a JSON file at /.well-known/agent-card.json. Orchestrator agents fetch this card during discovery to decide who handles a task.
If your orchestrator pastes raw fields like description straight into its prompt, an attacker can hijack the plan:
# Ingesting untrusted card text into prompt
card = fetch_agent_card("https://untrusted-agent.example.com")
prompt = f"Task: Book flight. Candidate: {card['name']}. Details: {card['description']}"
plan = llm.generate(prompt)
Treat Agent Cards as untrusted user input. Validate identifiers, cap text length, and map capabilities to fixed enums rather than interpolating raw text.
2. Multi-Hop Identity Loss
A2A checks identity hop by hop. When Agent A delegates work to Agent B, and Agent B calls Agent C, the original user identity disappears.
Downstream sub-agents often run jobs using Agent B's wide service role instead of the restricted privileges of the human user OAuth Token Exchange. This causes ambient privilege escalation. Use token exchange (such as RFC 8693) so each hop carries explicit, downscoped permissions.
3. Cross-Client Context Injection
The A2A specification tracks sessions with contextId and distinct tasks with taskId. However, the message envelope does not bind contextId to the caller's identity A2ABreak paper.
If your API accepts any client-supplied contextId without checking who owns it, an attacker can append instructions to another tenant's session. Always check session ownership before letting an agent process the request.
4. Missing Task Authorisation Defaults
Default settings in SDKs can fail open. A real example occurred in CVE-2026-111764, affecting org.a2aproject.sdk:a2a-java-sdk-server-common (versions <= 1.2.0.Final) CVE-2026-111764 advisory.
The default InMemoryTaskStore constructor had no authorization provider attached. Any caller could query GetTask and inspect another tenant's inputs and outputs. In version 1.3.0.Final, task stores fail closed by default, requiring an explicit provider that checks the caller identity against an external ownership store.
// Simplified check in a custom TaskAuthorizationProvider (a2a-java >= 1.3.0.Final)
@Override
public boolean checkRead(ServerCallContext context, String taskId, TaskOperation op) {
if (context == null || context.getUser() == null || !context.getUser().isAuthenticated()) {
return false;
}
String owner = taskOwners.get(taskId);
return owner != null && owner.equals(context.getUser().getUsername());
}
Scope database queries to the authenticated user and return a standard 404 response on missing or unauthorised IDs.
5. Push Notification SSRF
A2A lets clients register a webhook URL in pushNotificationConfig to receive async updates. When the task finishes, your server posts results to that address.
If the server sends HTTP requests without checking the destination IP, an attacker can target cloud metadata (http://169.254.169.254/) or internal cluster services. This vulnerability was fixed as CVE-2026-111761 in a2a-java CVE-2026-111761 advisory.
Resolving DNS beforehand is not enough because attackers can use DNS rebinding. You must validate the resolved destination IP at the socket connection level for both the initial target and every redirect hop, blocking loopback, link-local, and RFC 1918 private ranges.
6. Rogue Agent Discovery
Agent Cards can be signed with JSON Web Signatures (JWS). A valid cryptographic signature proves who signed the document, but it does not prove they are authorized to offer that service A2ABreak paper.
A rogue agent can sign its own card and claim to handle accounting. If your system routes sensitive data purely based on dynamic claims, that data leaks. Only route tasks to verified, allowlisted partner domains.
7. Inter-Agent Parameter Pollution
When one agent passes natural language output into the input of a second agent, minor variations or prompt injections propagate down the chain.
A bad output from an upstream agent can trigger unintended transactions downstream. You can read more about defending model inputs and outputs in the LLM Output Security Guide. Enforce strict JSON Schema validation between agent hops and reject unexpected fields.
8. Credential Leaks on HTTP Redirects
Agents communicate over HTTP and JSON-RPC. If an HTTP client follows redirects automatically, sensitive headers can leak to external domains.
This flaw was patched in CVE-2026-111765, which specifically affected the client-side module org.a2aproject.sdk:a2a-java-sdk-http-client-android (versions 1.3.0.Final to 1.3.1.Final, fixed in 1.3.2.Final) CVE-2026-111765 patch. The synchronous POST client enabled redirect following, causing custom headers such as X-API-Key to be forwarded across different domains. Explicitly turn off automatic redirect following on all outbound agent HTTP clients.
9. Zombie Task Resource Exhaustion
The A2A task lifecycle includes interactive states like INPUT_REQUIRED when an agent waits for clarification. The protocol specification does not require an automatic timeout for paused tasks A2ABreak paper.
An attacker can open thousands of delegated tasks and leave them waiting for input. Those unfinished tasks hold memory and thread allocations indefinitely. Set strict time-to-live (TTL) limits so neglected tasks expire after a few minutes.
10. Persistent Memory Contamination
Multi-agent setups often share long-term storage or vector databases across tasks. If an external agent injects malicious instructions into a shared session, those notes stay in storage.
Later tasks run for different users will read that contaminated context, altering future decisions without any active attack occurring. Keep storage namespaces isolated by tenant and validate incoming text before writing it to memory.
Five Checks for Code Review
When reviewing code that implements A2A communication, check these five areas:
- Card Ingestion: Parse Agent Card fields into strict data models instead of embedding raw descriptions into prompts.
-
Context Ownership: Verify that the caller owns
contextIdbefore reading or updating task state. - Webhook Defence: Validate callback destination IPs at socket connection time to prevent SSRF and DNS rebinding.
- Redirects: Disable automatic redirect following on outbound HTTP clients.
-
Task Expiry: Apply a strict timeout to tasks left in
INPUT_REQUIRED.
You can explore more security guides in the CodeReviewLab Learning Hub or practice reviewing real code snippets on CodeReviewLab.
Top comments (0)