Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/services/a2aService.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

const MandateService = require("./mandate");
const logger = require("../utils/logger");
const MandateService = require("./mandate");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expired mandate message double-wrapped

Medium Severity

The executeTransfer function unconditionally wraps errors from its initial mandate check, including the Zero Trust Validation Failed: Mandate has expired error from verifyMandate. This results in A2A callers receiving a nested error message for expired mandates, rather than the intended canonical expiry string.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5396231. Configure here.


class A2AService {
constructor(walletService, db, config = {}) {
Expand Down
2 changes: 1 addition & 1 deletion src/services/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class AgentService {

if (perTransactionLimit > 0 && amount > perTransactionLimit) {
throw new Error(
`Zero Trust Validation Failed: Transfer amount ${amount} exceeds per-transaction limit of ${perTransactionLimit} for agent ${fromAgentId}`,
`Zero Trust Validation Failed: Amount ${amount} exceeds agent per-transaction limit of ${perTransactionLimit}`,
);
}

Expand Down
5 changes: 4 additions & 1 deletion src/services/mandate.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class MandateService {
try {
decoded = jwt.verify(token, this.signingKey, { algorithms: ["HS256"] });
} catch (error) {
if (error.name === "TokenExpiredError") {
throw new Error("Zero Trust Validation Failed: Mandate has expired");
}
throw new Error(
`Zero Trust Validation Failed: Mandate verification failed: ${error.message}`,
);
Expand All @@ -135,7 +138,7 @@ class MandateService {
if (context.recipient && decoded.allowed_merchants?.length > 0) {
if (!decoded.allowed_merchants.includes(context.recipient)) {
throw new Error(
`Zero Trust Validation Failed: Recipient ${context.recipient} not authorized by mandate`,
`Zero Trust Validation Failed: Merchant ${context.recipient} not authorized by mandate`,
);
}
}
Expand Down
7 changes: 4 additions & 3 deletions tests/unit/agent.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('AgentService', () => {
mockA2AService = {
executeTransfer: jest.fn()
};
agentService = new AgentService(mockDb, {}, mockA2AService);
agentService = new AgentService(mockDb, {});
});

describe('registerAgent', () => {
Expand Down Expand Up @@ -55,7 +55,7 @@ describe('AgentService', () => {
fromAgentId: 'agent1',
toAgentId: 'agent2',
amount: 100
})).rejects.toThrow(/Zero Trust Validation Failed: Transfer amount 100 exceeds per-transaction limit of 50/);
})).rejects.toThrow(/Zero Trust Validation Failed: Amount 100 exceeds agent per-transaction limit of 50/);
});

it('should throw if counterparty is not authorized', async () => {
Expand Down Expand Up @@ -101,7 +101,8 @@ describe('AgentService', () => {
const expectedResult = { success: true, transferId: 'tx123' };
mockA2AService.executeTransfer.mockResolvedValue(expectedResult);

const result = await agentService.performA2ATransfer(transferParams);
const delegatingAgentService = new AgentService(mockDb, {}, mockA2AService);
const result = await delegatingAgentService.performA2ATransfer(transferParams);

expect(mockA2AService.executeTransfer).toHaveBeenCalledWith({
fromAgentId: 'agent1',
Expand Down
Loading