Skip to content

[Bug]: A2A response handshakes return request nonce instead of fresh reply nonce #174

Description

@Kewe63

Affected package or area

@agentcommercekit/ack-id

Affected version, release, or commit

@agentcommercekit/ack-id 0.11.0, ACK commit 0b8fdaa

Environment

  • Node.js: v24.14.1
  • Package manager and version: pnpm 11.8.0
  • Operating system: WSL2 / Linux

Summary

createA2AHandshakeMessage() returns the wrong nonce when creating a response handshake with requestNonce.

When requestNonce is provided, createA2AHandshakePayload() correctly puts the initiator's nonce in payload.nonce and the newly generated nonce in payload.replyNonce. However, createA2AHandshakeMessage() always returns nonce: payload.nonce, so callers receive the peer's old request nonce instead of the fresh reply nonce they need to correlate the next handshake leg.

Minimal reproduction and steps

  1. In packages/ack-id/src/a2a/sign-message.test.ts, add a regression test that calls createA2AHandshakeMessage() with requestNonce.
  2. Mock generateRandomNonce() to return fresh-reply-nonce.
  3. Call createA2AHandshakeMessage("agent", { recipient: userDid, vc: testCredential, requestNonce: "initiator-nonce" }, { did: agentDid, jwtSigner }).
  4. Assert that result.nonce is fresh-reply-nonce.
  5. Run:

pnpm run build
pnpm --filter @agentcommercekit/ack-id test -- src/a2a/sign-message.test.ts

Expected behavior

When requestNonce is provided, createA2AHandshakeMessage() should return the freshly generated replyNonce so callers can store and correlate the next handshake leg.

Actual behavior

createA2AHandshakeMessage() returns payload.nonce, which is the peer's original requestNonce. The fresh nonce is only present in payload.replyNonce and is not returned to the caller.

Relevant code

packages/ack-id/src/a2a/sign-message.ts

const payload = createA2AHandshakePayload(params)
return {
  sig: jwt,
  jti,
  nonce: payload.nonce,
  message,
}

Observed failing assertion

Expected: fresh-reply-nonce
Received: initiator-nonce

Suggested fix

Return payload.replyNonce when it exists, otherwise keep the current initiator behavior.

nonce: payload.replyNonce ?? payload.nonce

AI usage

This issue was found and validated with assistance from Hermes Agent.

Acknowledgements

  • I searched existing open and closed issues for this problem.
  • This report does not describe a suspected security vulnerability.
  • I removed secrets, credentials, personal data, and other sensitive information from this report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions