SW-A2A-002: Agent card uses a format older than A2A 1.0
Last updated 7 November 2026
| Fact | Value |
|---|---|
| Severity | Medium |
| Checks | A2A agent card |
| Malicious indicator | No |
| OWASP Agentic Top 10 | ASI07 |
| OWASP MCP Top 10 | None mapped |
| NIST SP 800-53 | SI-10 (provisional mapping to SP 800-53 base controls) |
| First shipped in | Scanner 1.3.0 |
What it detects
The rule decides the card's format first. A card with a supportedInterfaces member is 1.0. A card with a top-level url is 0.3 when it also has a signatures member or a protocolVersion that starts with 0.3, and 0.2 otherwise. A card in either old format gets one finding for the whole card, with the format as the reason, and is not judged against the old definitions.
A card in the 1.0 shape that still carries a member 1.0 removed or renamed gets one finding for each such member, at the member's JSON pointer. The members are the top-level url, preferredTransport, additionalInterfaces, protocolVersion, supportsAuthenticatedExtendedCard, supportsExtendedAgentCard and security; capabilities.stateTransitionHistory; a skill's security; an interface's transport; a security scheme's type; and an API key scheme's in. Since scanner 1.5.0 the snake_case names of these members are read as the same members.
Why it matters
A2A 1.0 changed how a card names its endpoints, its security and its extended card. A card in the old format, or a 1.0 card that keeps old members next to the new ones, makes clients disagree about which endpoint and which authentication apply. A client that reads 1.0 follows the interface list and the security requirements, and a client that reads 0.3 follows the url and the security member. A reviewer who checked one reading has not checked the other. The scanner maps this rule to OWASP ASI07, Insecure Inter-Agent Communication, and to NIST SP 800-53 control SI-10, Information Input Validation.
Signing adds a second reason. The signature rules treat these old members as part of what a signature must cover (SW-A2A-010), because clients still read them.
Example
This card is in the 0.3 shape: one url in place of the interface list, with a protocolVersion, a preferredTransport, a type on its scheme and a security list:
.well-known/agent-card.json
{
"name": "demo-agent",
"description": "Drafts release notes from merged pull requests.",
"url": "https://agent.example.invalid/a2a",
"version": "1.0.0",
"protocolVersion": "0.3.0",
"preferredTransport": "JSONRPC",
"capabilities": {},
"securitySchemes": {
"bearer": {
"type": "http",
"scheme": "Bearer"
}
},
"security": [
{
"bearer": []
}
],
"defaultInputModes": [
"text/plain"
],
"defaultOutputModes": [
"text/plain"
],
"skills": [
{
"id": "release-notes",
"name": "Release notes",
"description": "Drafts release notes for one tag.",
"tags": [
"release"
]
}
]
}The scanner reports the card as format 0.3 in one finding, at the top of the file. It does not list the old members one by one, because the whole card is the problem. The report adds a migration status and a checklist for it.
How to fix
Move the card to 1.0. Replace url and additionalInterfaces with supportedInterfaces, each entry holding a url, a protocolBinding and a protocolVersion. Replace security with securityRequirements in its schemes-and-list form. Wrap each security scheme in its kind, such as httpAuthSecurityScheme or oauth2SecurityScheme, instead of giving it a type member. Remove the top-level protocolVersion, which now lives on each interface.
Sign the card again when the move is done, because the old signature covered the old members, and scan again.
If it is a false positive
A repository that keeps a 0.3 card on purpose, because it still serves clients that have not moved to 1.0, gets this finding on every scan. Accept it with a note that names those clients and the date the old card goes. The finding disappears when the card is rewritten.
If the finding is not a problem in your case, accept it with a note: in the dashboard a manager or owner can accept a finding and the note is kept with it; with the scanner on its own, add it to the baseline file with a reason and an expiry date.