Skip to content

fix(tss): verify recipients before signing#8539

Open
mrdanish26 wants to merge 1 commit intomasterfrom
fix/WAL-375-recipients-guard-v2
Open

fix(tss): verify recipients before signing#8539
mrdanish26 wants to merge 1 commit intomasterfrom
fix/WAL-375-recipients-guard-v2

Conversation

@mrdanish26
Copy link
Copy Markdown
Contributor

@mrdanish26 mrdanish26 commented Apr 16, 2026

TICKET: WAL-375

Description

Ensures verifyTransaction always receives recipient details before any signing material is sent to BitGo, preventing a compromised API from silently substituting signableHex with attacker-controlled bytes.

A resolveEffectiveTxParams() guard is added to both ECDSA and MPCv2 signRequestBase() paths. It resolves recipients from three sources in priority order:

  1. txParams.recipients — normal case.
  2. txRequest.intent.recipients — fallback for smart-contract interactions (e.g. Tempo supplyController) where native ETH amount = 0 so buildParams is empty but intent carries the recipients.
  3. No-recipient tx types (tokenApproval, acceleration, fillNonce, bridgeFunds, consolidate, transferToken) — guard skipped; verifyTransaction handles validation internally.

Shared logic is extracted to tss/ecdsa/base.ts (NO_RECIPIENT_TX_TYPES + resolveEffectiveTxParams) to avoid duplication between the two signing paths.

A previous PR (#8462) hard-threw on any empty recipients, breaking cases 2 and 3. It was reverted in #8538. This PR supersedes it.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Testing

Added 4 new unit tests to each signing path (8 total):

  • signTxRequest should succeed when recipients are only in intent — validates intent fallback
  • signTxRequest should succeed for no-recipient tx types (tokenApproval) — exemption
  • signTxRequest should succeed for no-recipient tx types (acceleration) — exemption
  • signTxRequest should prefer txParams.recipients over intent.recipients when both present — priority

@linear
Copy link
Copy Markdown

linear bot commented Apr 16, 2026

@mrdanish26 mrdanish26 force-pushed the fix/WAL-375-recipients-guard-v2 branch from e444156 to 2d64d76 Compare April 17, 2026 00:17
@mrdanish26 mrdanish26 marked this pull request as ready for review April 17, 2026 02:28
@mrdanish26 mrdanish26 requested review from a team as code owners April 17, 2026 02:28
@sachushaji
Copy link
Copy Markdown
Contributor

@claude

Comment on lines +12 to +58
/**
* Transaction types that legitimately carry no explicit recipients.
* verifyTransaction handles no-recipient validation for these internally.
* Mirrors the bypass list in abstractEthLikeNewCoins.ts verifyTssTransaction.
*/
export const NO_RECIPIENT_TX_TYPES = new Set([
'acceleration',
'fillNonce',
'transferToken',
'tokenApproval',
'consolidate',
'bridgeFunds',
]);

/**
* Resolves the effective txParams for TSS signing recipient verification.
*
* For smart contract interactions, recipients live in txRequest.intent.recipients
* (native amount = 0, so buildParams is empty). Falls back to intent recipients
* mapped to ITransactionRecipient shape when txParams.recipients is absent.
*
* Throws InvalidTransactionError if no recipients can be resolved and the
* transaction type is not a known no-recipient type.
*/
export function resolveEffectiveTxParams(
txRequest: TxRequest,
txParams: TransactionParams | undefined
): TransactionParams {
const intentRecipients = (txRequest.intent as PopulatedIntent)?.recipients?.map((intentRecipient) => ({
address: intentRecipient.address.address,
amount: intentRecipient.amount.value,
data: intentRecipient.data,
}));

const effectiveTxParams: TransactionParams = {
...txParams,
recipients: txParams?.recipients?.length ? txParams.recipients : intentRecipients,
};

if (!effectiveTxParams.recipients?.length && !NO_RECIPIENT_TX_TYPES.has(effectiveTxParams.type ?? '')) {
throw new InvalidTransactionError(
'Recipient details are required to verify this transaction before signing. Pass txParams with at least one recipient.'
);
}

return effectiveTxParams;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what about eddsa ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants