Security requirements
Sections 13 and 14 list what a server and a client MUST and SHOULD check, and most of those checks fall on data that another agent sent.
The planner reads review.json from code-reviewer and the test-log.txt chunks from test-runner, registers a webhook at localhost:41250, and sends a bearer token to deployer. Each step crosses a boundary between two parties, and no field in A2A marks what crosses it as safe. Sections 13 and 14 of the specification say what each side must check at those boundaries.
When you finish this section, you can name the rule that applies at each boundary, and say whether the kit and the SDKs meet it. Figure 6.3 maps six boundaries in the kit, with the check at each.
The requirements, and who meets them
The table lists each rule in §13 and §14 that binds a server or a client with a MUST or a SHOULD. The kit column says where the kit meets the rule or does not. The SDK column gives the comparison of the six official SDKs where one was made, with a link to the section that owns the detail.
| Rule | The kit | The SDKs |
|---|---|---|
| A server must check authorization on every A2A operation request | none per caller: the deployer needs one shared token, and the other two agents accept anyone | none includes authentication, and owner scoping differs, as security schemes tables |
GetExtendedAgentCard must require authentication | the deployer checks its bearer token before every method | none in the core handlers, as extended cards tables |
| An agent must put authentication credentials in its webhook requests | Authorization: Bearer hook_secret_91d2 on every POST | every SDK that pushes. a2a-go and a2a-rs send only the Bearer and Basic schemes, and a2a-dotnet has no sender |
| An agent should validate webhook URLs against SSRF | accepts http://localhost:41250/a2a-events, because every process runs on one machine | a2a-go, a2a-rs, and a2a-java reject private hosts by default. a2a-python has an opt-in validator, and the notes record no check in a2a-js |
| An agent should set reasonable timeouts on webhook requests and should retry | 10 s, and no retry | 5 s in a2a-js, 30 s in a2a-go and a2a-rs, the HTTP client default in a2a-python and a2a-java, and none retries |
| A client must check each webhook with the credentials it gave | the planner's receiver records the headers and checks nothing | not compared, and push notifications lists the receiver's duties |
| A client should use a unique token with one purpose for each push notification config | one token per run, and a read returns it in clear | the reference SDK returns stored credentials in clear too, as push notifications shows |
| An agent must validate every input parameter before it processes a request. It should check file content types and reject media types that it does not expect | a missing field answers -32602 with a BadRequest detail, and code-reviewer refuses a url part with image/png | the reference SDK's media type check is off by default, as the kit README lists |
| An implementation must sanitize content from users against injection attacks | the planner decides on typed data fields only | not compared |
| File references in A2A messages must be validated against server-side request forgery (SSRF) | code-reviewer fetches no URL | not compared |
| Logs must not hold credentials or personal data, unless they are needed and protected | the capture files hold dpl_test_7c1e4b and hook_secret_91d2, which are test values | not compared |
| An implementation should serve the Agent Card over HTTPS, and a client should verify signatures when the card has them | the planner fetches cards over plain HTTP and verifies nothing, and 17-signed-card.txt shows the check | not compared, and extended cards and signatures covers verification |
| An agent should rate-limit every operation and should log security events | none | not compared |
Three of those rules deserve more than a row, because the data they guard arrives in every task.
Text is data, even when it reads like an order
Prompt injection: text that arrives as data and that a model on the receiving side follows as an instruction. No field of a part says how far to trust its content, and review.json was built from a diff that other people wrote.
The kit's planner decides from data parts. It reads failed from summary.json and severity from each finding in review.json, and ignores the free text beside them. Its one use of remote text is a substring test on the reviewer's question. A planner built on a model reads much more. So act only on typed fields you have checked. Keep side effects behind an approval that a person or a policy controls, as the deployer does.
URLs aim the receiver's own requests
Server-side request forgery (SSRF): a server sends a request to an address that an outside caller chose, such as an internal service. A url part invites it, and so does a webhook URL, which the agent calls for every later event of the task.
The kit's code-reviewer refuses a url part with media type image/png, because its input modes do not list it, and fetches nothing. For webhooks, the specification asks agents to reject the private ranges 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16.
They also reject localhost and link-local addresses. The kit accepts http://localhost:41250/a2a-events only because every process runs on one machine. The reference SDK's validator rejects hosts that resolve to loopback, private, link-local, reserved, multicast, or unspecified addresses. It runs only when the host turns it on. Push notifications covers the receiver's checks.
Records that outlive the task
A read of a stored configuration returns its secret in clear:
"configs": [
{
"id": "92c697ef-4abc-4e86-82ba-dc6bce4077af",
"taskId": "d7d3dceb-7333-4676-90ce-36542116a45c",
"url": "http://localhost:41250/a2a-events",
"token": "planner-run-0006",
"authentication": {
"scheme": "Bearer",
"credentials": "hook_secret_91d2"These reads need the task's own access check, and security schemes covers that scope. The capture files hold dpl_test_7c1e4b and hook_secret_91d2 in clear, which is safe only because they are test values. The refunds.diff part stays in the review task's history. Sensitive information in task history and artifacts must be protected as the data protection rules require. Set a retention period for all of it, as §13.4 recommends.
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10