Skip to content

fix(sdk-coin-bsc,sdk-coin-xdc): harden TSS verify via serializedTxHex - #9403

Open
bitgo-ai-agent-dev[bot] wants to merge 3 commits into
masterfrom
wci-1169-bsc-remove-weak-verifytsstransaction
Open

fix(sdk-coin-bsc,sdk-coin-xdc): harden TSS verify via serializedTxHex#9403
bitgo-ai-agent-dev[bot] wants to merge 3 commits into
masterfrom
wci-1169-bsc-remove-weak-verifytsstransaction

Conversation

@bitgo-ai-agent-dev

@bitgo-ai-agent-dev bitgo-ai-agent-dev Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Remove weak verifyTssTransaction stubs from BSC/XDC (Bsc/BscToken, Xdc/XdcToken) that returned true after only shallow presence checks, so they inherit AbstractEthLikeNewCoins transfer validation
  • In ECDSA MPCv1/v2, pass serializedTxHex (like ICP) for bsc/xdc during verify — legacy EIP-155 signableHex (RLP with v=chainId) fails ethereumjs fromSerializedTx, which is why the stubs existed
  • Add regression tests for native and ERC-20/BEP-20 matching/mismatched recipients (BSC also covers WalletConnect recipients[0].data)

Why

  • Audit finding, tracked as WCI-1102WCI-1169
  • Original ovverrides were added for a txHex decode crash; the decode path works when given serializedTxHex

Test plan

  • yarn run unit-test --scope @bitgo/sdk-coin-bsc
  • yarn run unit-test --scope @bitgo/sdk-coin-xdc
  • Native BNB/XDC matching recipient → passes
  • Native transfer with mismatched recipient → throws
  • ERC-20/BEP-20 matching calldata → passes
  • ERC-20/BEP-20 mismatched calldata → throws
  • Staging smoke: TBSC/TXDC send hits inherited verify successfully

Ticket: WCI-1169

@linear-code

linear-code Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

WCI-1169

@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1169-bsc-remove-weak-verifytsstransaction branch from a180e39 to b505c8b Compare August 3, 2026 10:24
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1169-bsc-remove-weak-verifytsstransaction branch from b505c8b to b968966 Compare August 3, 2026 10:24
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1169-bsc-remove-weak-verifytsstransaction branch from 2e6ca82 to 98afd5e Compare August 3, 2026 11:11
@bitgo-ai-agent-dev bitgo-ai-agent-dev Bot changed the title fix(bsc): remove weak verifyTssTransaction override, inherit base class fix(bsc): port transfer validation from base class into verifyTssTransaction Aug 3, 2026
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1169-bsc-remove-weak-verifytsstransaction branch from 652bec2 to 6c6f12a Compare August 3, 2026 11:14
Marzooqa and others added 2 commits August 4, 2026 17:11
Remove the weak verifyTssTransaction stubs from Bsc/BscToken so they
inherit AbstractEthLikeNewCoins validation. Pass serializedTxHex for
BSC (and XDC) in ECDSA MPCv1/v2 verify paths because legacy EIP-155
signableHex fails ethereumjs fromSerializedTx.

Ticket: WCI-1169
Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the unconditional-return-true stubs from Xdc/XdcToken so they
inherit AbstractEthLikeNewCoins transfer validation. Relies on the
sdk-core serializedTxHex verify path for legacy EIP-155.

Ticket: WCI-1169
Co-authored-by: Cursor <cursoragent@cursor.com>
@Marzooqa
Marzooqa force-pushed the wci-1169-bsc-remove-weak-verifytsstransaction branch from 93797f2 to 67c754e Compare August 4, 2026 11:42
@Marzooqa Marzooqa changed the title fix(bsc): port transfer validation from base class into verifyTssTransaction fix(sdk-coin-bsc,sdk-coin-xdc): harden TSS verify via serializedTxHex Aug 4, 2026
@Marzooqa
Marzooqa marked this pull request as ready for review August 4, 2026 12:28
@Marzooqa
Marzooqa requested review from a team as code owners August 4, 2026 12:28
parasgarg-bitgo
parasgarg-bitgo previously approved these changes Aug 4, 2026
Comment on lines +814 to +822
// For some coins, signableHex is not a parseable transaction. Pass
// serializedTxHex so verifyTransaction can decode the full tx bytes.
// - ICP: signableHex is a hash; serializedTxHex is the CBOR-encoded tx.
// - BSC/XDC (legacy EIP-155): signableHex is RLP(..., chainId, 0, 0), which
// fails ethereumjs fromSerializedTx EIP-155 v validation; serializedTxHex
// is the unsigned broadcast form and parses cleanly.
// For other coins, verification is typically done using just the signableHex.
const coinFamily = this.baseCoin.getConfig().family;
if (coinFamily === 'icp' || coinFamily === 'bsc' || coinFamily === 'xdc') {

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.

this isn't a scalable pattern, we should mark this in a config somewhere. There's CoinFeature we can put it under.

Comment on lines +955 to +959
const coinFamily = this.baseCoin.getConfig().family;
const isIcp = coinFamily === 'icp';
const isLegacyEip155Evm = coinFamily === 'bsc' || coinFamily === 'xdc';
const isPreHashed = shouldUsePreHashedSignable(this.baseCoin, unsignedTx);
if (isIcp || isPreHashed) {
if (isIcp || isPreHashed || isLegacyEip155Evm) {

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.

we can refactor this per above.

Replace hard-coded icp/bsc/xdc family checks with
CoinFeature.TSS_VERIFY_USE_SERIALIZED_TX_HEX on BSC, XDC, and ICP
(and their tokens), so new coins can opt in via statics config.

Ticket: WCI-1169
Co-authored-by: Cursor <cursoragent@cursor.com>
@Marzooqa
Marzooqa force-pushed the wci-1169-bsc-remove-weak-verifytsstransaction branch from db2c9f6 to e3192f7 Compare August 4, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants