fix(sdk-core): enforce recipient verification in EdDSA TSS signing#9071
Conversation
5c3c229 to
4a14137
Compare
mohammadalfaiyazbitgo
left a comment
There was a problem hiding this comment.
lgtm, but we should add some unit tests
089706d to
9da68df
Compare
077e837 to
9c7bd6e
Compare
Review: blocking concern —
|
zahin-mohammad
left a comment
There was a problem hiding this comment.
@mrdanish26 can you take a look at the claude review and see if it's valid.
9c7bd6e to
b131347
Compare
The audit queried the signingGuard Loki metric and it only fires for no-recipient signing events, so it covered no-recipient types with live traffic, not all EdDSA intentTypes.
This was missed, cross-referenced against
EdDSA staking types (stake, unstake, bond, delegate etc.) are directly in NO_RECIPIENT_TX_TYPES and bypass via set membership. The stakingRequestId bypass is secondary fallback for any staking type not explicitly in the set. No EdDSA staking flow depends solely on it. |
TICKET: WCN-196
Problem
EdDSA TSS signing paths have no recipient verification before signing:
eddsa.ts (MPC v1): No
verifyTransactioncall at all. After resolving theunsigned tx, the code proceeds directly to MPC signing rounds with zero verification
that the transaction recipients match the intent.
eddsaMPCv2.ts (MPC v2): Has a
verifyTransactioncall but usesparams.txParams || { recipients: [] }, which always falls back to an emptyrecipients array — making the recipient check in
verifyTransactiona no-op.This means an attacker who can manipulate the txPrebuild (the actual transaction bytes)
can substitute different recipient addresses without detection on any EdDSA coin
(SOL, ADA, SUI, TON, DOT, APT, NEAR, CANTON, IOTA, TAO).
This is the EdDSA counterpart to the ECDSA fix in #8924.
Fix
eddsa.ts: Add
verifyTransactioncall withresolveEffectiveTxParamsto resolverecipients from
txRequest.intent(server-side truth) and verify them against thetxPrebuild before signing.
eddsaMPCv2.ts: Replace
params.txParams || { recipients: [] }withresolveEffectiveTxParams(txRequest, params.txParams)so the existingverifyTransactioncall receives actual recipients for comparison.recipientUtils.ts: Add EdDSA-specific no-recipient transaction types to
NO_RECIPIENT_TX_TYPES:closeAssociatedTokenAccount(SOL),voteDelegation(ADA),transferAcknowledge(CANTON).Verification
recipientUtilsunit tests passing (12/12).