A2A Agent Card Signing: Build a Verifier Pack
A2A Agent Card signatures use RFC 7515 JSON Web Signature fields over a canonicalized card representation. A safe rollout needs deterministic canonicalization, trusted-signer resolution, signature verification, tamper tests, unknown-signer behavior, rotation, unsigned-card policy, and evidence capture. This guide turns those requirements into a verifier pack for discovery and trust decisions.

An A2A Agent Card describes an agent's interfaces and capabilities, plus its skills and security schemes. A2A v1 adds a signature mechanism based on RFC 7515 JSON Web Signature. The verifier must canonicalize the card, exclude the signatures field from the signed content, resolve a trusted public key, and reject a card when any protected byte has changed.
That sounds compact until the first rotation. Put two card files on the desk, change one endpoint character in the second file, and make the verifier explain its decision. The rollout artifact should contain the canonical payload hash and selected signer, plus the signature result and retrieval evidence covering cache state and failure reason, without confusing card authenticity with authorization to perform an action.
TL;DR
- Canonicalize the Agent Card deterministically with RFC 8785 rules, excluding
signaturesfrom the signed representation before generating or verifying JWS. - Resolve verification material through an approved trust policy. Treat a syntactically valid
jkuas a pointer to evaluate, never as automatic authority. - Test tampering and unknown signers. Also test expired or revoked credentials and algorithm restrictions, followed by rotation overlap and stale caches. Exercise unsigned cards before enforcement.
- Agent Card publication and discovery sit outside DeepInspect. Signing and A2A messages do too. A later routed HTTP LLM request is a separate control decision.
The signed object needs one byte representation
The A2A specification defines AgentCardSignature as a JWS signature following RFC 7515's JSON format. The object contains a protected header and computed signature, with optional header fields. A verifier still needs an exact payload representation because equivalent JSON can differ in whitespace or property order. Number formatting can differ too.
A2A v1 addresses that problem through RFC 8785 JSON Canonicalization Scheme. The A2A v1 change summary identifies RFC 8785 and RFC 7515 as dependencies. It also describes detached signatures with public-material retrieval through jku or trusted stores.
Implement canonicalization as a shared library used by signer and verifier. Remove the top-level signatures field from the input copy and canonicalize the remaining card. Encode the bytes exactly as required by the chosen JWS serialization, then sign those bytes. Preserve a hash of the canonical payload in test evidence. Do not mutate the card object in place because a retry can accidentally sign a previously added signature.
Key resolution is the trust decision
Signature mathematics proves that a private key corresponding to the selected public key produced the signature. Trust policy decides whether that signing identity is authorized to speak for the Agent Card's identity and endpoint.
Create an allowlist for approved issuers and trusted signer stores. Maintain a separate allowlist for jku origins. Require HTTPS and validate the certificate chain and hostname. Set response-size and content-type limits. Block redirects to unapproved hosts. Protect the fetcher against private address ranges and metadata endpoints. Cache verification material by stable identifier with a bounded lifetime, then define behavior when the retrieval endpoint is unavailable.
Set an explicit list of accepted algorithms. Reject none and unsupported choices. Reject protected headers that conflict with local policy. If the protected header carries kid, require an unambiguous match. Record the selected JWK thumbprint, source, cache state, algorithm, and trust-policy version with every decision.
I would keep remote public-material retrieval disabled until the team can show an SSRF test and a stale-cache test in the same review packet.
The verifier pack needs failure-first tests
Build the pack from a known-good card, its canonical bytes, the signer credential, and its signature. Record the expected decision separately. Then derive negative fixtures by changing one property at a time.
- Payload tamper: Change the endpoint or skill. Changes to the security scheme and capability should also be tested. Test the provider field as well. Verification should fail with a payload-integrity reason.
- Signature tamper: Flip one base64url character in the signature. The verifier should reject the card without attempting a different credential silently.
- Unknown signer: Supply an unrecognized
kidor unapprovedjku. The result should distinguish unknown trust from invalid cryptography. - Algorithm change: Replace the accepted algorithm with a blocked option. The policy rejection should occur before application use.
- Canonicalization variants: Reorder properties and change irrelevant whitespace. The signature should remain valid when the JSON value is equivalent under RFC 8785.
- Excluded-field change: Add or reorder entries inside
signatures. Verification of the underlying card should still use the representation with that field excluded. - Fetch failure: Simulate timeout and an oversized verification set. Also test a redirect and invalid TLS. Test private-address resolution and malformed JSON too.
- Unsigned card: Exercise permit, warn, quarantine, or reject behavior according to the rollout phase and card source.
Give every fixture a stable ID and expected reason code. The signed audit logs guide covers integrity for a different artifact, but its separation of payload hash and signing identity is useful when designing this test evidence. The verification result should remain separate too.
Rotation needs overlap and cache controls
Rotate with two credentials published during an overlap window. Sign new cards with the new credential while verifiers continue accepting valid signatures from the retiring credential until the declared cutoff. Record issuance time and activation time. Also record retirement time and revocation reason. Record the cache maximum age separately.
Test four moments: before activation, during overlap, after retirement, and after emergency revocation. A verifier with cached old material should refresh or reject according to the written policy. It should never keep accepting a revoked credential because the cache entry lacks a revocation path.
Multiple signatures can support transition when local policy permits them, provided the policy defines its acceptance threshold explicitly. "Any valid signature" differs from "one signature from the current production trust set." Preserve which signature satisfied policy and why the remaining signatures were ignored or rejected.
Treat rollback as a content change because restoring an older Agent Card can reintroduce a retired endpoint or capability even when its signature remains cryptographically valid. Bind rollback approval to the card version or content hash, then review the semantic change separately from signature validity.
Rollout should separate verification from authorization
Start in report-only mode by fetching cards from approved discovery routes. Verify signatures and record decisions without blocking. Measure unsigned cards and unknown signers separately. Track stale caches and fetch errors apart from semantic changes. Fix producer and trust-store defects before enforcement.
Move approved issuers to enforcement in bounded groups. Keep unsigned or untrusted cards in quarantine, where operators can inspect them without making their claims available to production routing. Store the original card and canonical payload hash. Retain signature metadata, the selected JWK thumbprint, trust-policy version, result, reason, and verifier build.
A valid signature authenticates card content under the configured signer trust. It does not authorize the discovering user to invoke every skill or prove that the agent is safe. It also does not validate a later A2A task. The MCP versus A2A protocol comparison places Agent Cards in discovery and capability description. Runtime authentication and delegated authority remain separate controls, along with destination permissions and task-level policy.
DeepInspect
A2A Agent Card discovery and canonicalization remain outside DeepInspect's enforcement boundary. Public-material retrieval and signature verification remain outside it. Tasks and inter-agent messages do too. A valid card does not establish authorization for a later model request, and DeepInspect cannot attest that an Agent Card verifier applied RFC 8785 correctly.
DeepInspect applies only when a customer-controlled application deliberately routes an authenticated HTTP LLM request through its proxy. For that separate call, DeepInspect evaluates supplied identity context and model route. It also evaluates data classification and current policy before forwarding, then writes an independent decision record. Keep the card-verification ID beside the routed-request ID when correlation is useful, while preserving the separate authority of each record.
Book a technical deep dive at deepinspect.ai.
Frequently asked questions
- Should a verifier trust any HTTPS `jku` URL?
HTTPS protects transport to the resolved host but does not establish that the host is authorized for the Agent Card. Apply an origin allowlist or issuer-to-signer mapping and validate TLS and redirects. Block private destinations and limit the response, then record the selected JWK. Treat remote signer-material retrieval as a security-sensitive network client.
- Why exclude `signatures` before canonicalization?
Including the signature field creates a circular object because the signature would become part of the bytes being signed. Excluding the field gives signer and verifier a stable representation of the card's substantive claims. Test the exact exclusion behavior with fixtures because a library that removes the wrong nested field can create a different payload.
- Does a valid Agent Card authorize agent actions?
A valid signature proves that the canonicalized card matches a signing identity accepted by the verifier's trust policy. Authorization still depends on caller identity and delegated authority. Skill policy and destination permissions also apply to the specific task. Preserve the signature result as one input to those later decisions.
- What evidence should survive signing-credential rotation?
Keep the original card and canonical payload hash. Retain the protected header, signature, selected JWK thumbprint, signing-material source, trust-policy version, verification time, result, and reason code. Add activation and retirement records, plus revocation records for each credential. That packet lets a reviewer reconstruct what the verifier trusted at the time.