Skip to content

fix(sdk-core): wire resolveEffectiveTxParams into EddsaMPCv2Utils (WCI-1111) - #9394

Open
bitgo-ai-agent-dev[bot] wants to merge 2 commits into
masterfrom
wci-1111-wire-resolve-effective-tx-params-eddsa
Open

fix(sdk-core): wire resolveEffectiveTxParams into EddsaMPCv2Utils (WCI-1111)#9394
bitgo-ai-agent-dev[bot] wants to merge 2 commits into
masterfrom
wci-1111-wire-resolve-effective-tx-params-eddsa

Conversation

@bitgo-ai-agent-dev

Copy link
Copy Markdown
Contributor

What

  • eddsaMPCv2.ts signRequestBase: replaced the vulnerable params.txParams || { recipients: [] } fallback with resolveEffectiveTxParams(txRequest, params.txParams, this.baseCoin.getChain()). The function throws InvalidTransactionError when recipients cannot be resolved and the intent is not a recognised no-recipient type.
  • wallet.ts signTransactionTss: removed the EdDSA MPCv2 special-case block that pre-fetched the txRequest and called txParamsFromIntent before handing off to signTxRequest. That pre-fetch was introduced to work around the missing guard; now that resolveEffectiveTxParams owns intent-based derivation inside signRequestBase (which already fetches the txRequest internally when given a string ID), the wallet-layer duplication is redundant. Removed the now-unused txParamsFromIntent import.
  • Tests: added resolveEffectiveTxParams guard suite to signTxRequest.ts covering:
    • stakingAuthorize attack vector (no txParams, non-allowlisted intent → throws)
    • Empty-recipient txParams with non-allowlisted intent → throws
    • Allowlisted deactivate intentType with no txParams → succeeds
    • Allowlisted consolidate intentType with no txParams → succeeds
    • Intent-sourced recipients when txParams absent → succeeds
    • Staking intent with stakingRequestId signal → succeeds

Why

Trail of Bits finding TOB-BITGOEDMPC-1 (WCI-1100): the EdDSA MPCv2 re-sign path silently substituted an empty-recipients object when txParams was absent. Several coin-level verifyTransaction implementations (SOL, VET, Tempo, TRON) skip output-matching validation when recipients.length === 0, allowing a compromised BitGo server to present a malicious txHex that signs without any client-side validation.

ECDSA already used resolveEffectiveTxParams for fail-closed behaviour (ecdsaMPCv2.ts:958,965 and ecdsa.ts:821,828). This PR ports the same pattern to EdDSA MPCv2. MPCv1 (eddsa.ts) is explicitly out of scope per the ticket.

Depends on WCI-1110 (base branch wci-1110-fix-resolve-effective-tx-params-sol), which fixes resolveEffectiveTxParams to preserve tokenName for SOL token transfers and adds the deactivate/delegate/closeAssociatedTokenAccount allowlist entries needed by EdDSA coins.

Test plan

  • signTxRequest throws InvalidTransactionError for stakingAuthorize intent with no recipients and no txParams
  • signTxRequest throws for empty txParams.recipients with non-allowlisted intent
  • signTxRequest succeeds for deactivate and consolidate (allowlisted no-recipient intents)
  • signTxRequest succeeds when intent provides recipients and txParams is absent
  • signTxRequest succeeds for staking intents with stakingRequestId
  • Existing signing tests pass (user key, backup key, message signing, 429 retry)

Ticket: WCI-1111

@linear-code

linear-code Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

WCI-1111

@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 4807ac9 to 394740d Compare July 31, 2026 07:22
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch 2 times, most recently from 7e84969 to 1da40ae Compare July 31, 2026 07:48
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 1da40ae to eaae085 Compare July 31, 2026 07:48
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from eaae085 to ab7b2e9 Compare July 31, 2026 07:48
@Marzooqa
Marzooqa force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from ab7b2e9 to 63e90fc Compare July 31, 2026 07:53
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 63e90fc to 691bdbf Compare July 31, 2026 09:11
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 691bdbf to ce54229 Compare July 31, 2026 09:11
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from ce54229 to 0490122 Compare July 31, 2026 11:40
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 0490122 to e2ca6c4 Compare July 31, 2026 11:40
@Marzooqa
Marzooqa force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from e2ca6c4 to f4c6b60 Compare August 3, 2026 06:55
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from f4c6b60 to 0c44ba0 Compare August 3, 2026 08:59
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 0c44ba0 to 9a3286b Compare August 3, 2026 08:59
Base automatically changed from wci-1110-fix-resolve-effective-tx-params-sol to master August 3, 2026 09:04
@Marzooqa
Marzooqa force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 9a3286b to 9d6b87c Compare August 3, 2026 09:04
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch 2 times, most recently from 0db73c7 to 71040ea Compare August 3, 2026 09:20
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 71040ea to 3c040fc Compare August 3, 2026 09:20
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch 2 times, most recently from 9ba6e8d to 3b026eb Compare August 3, 2026 09:24
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 3b026eb to 18f65dd Compare August 3, 2026 09:24
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 18f65dd to cff0118 Compare August 3, 2026 09:24
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 4b4f135 to a70696a Compare August 3, 2026 10:01
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from a70696a to 9cb52b1 Compare August 3, 2026 10:01
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 7183351 to 7322e7d Compare August 3, 2026 10:05
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 7322e7d to 8e11038 Compare August 3, 2026 10:05
Replace the unsafe `params.txParams || { recipients: [] }` fallback in
`EddsaMPCv2Utils.signRequestBase` with `resolveEffectiveTxParams`, which
throws `InvalidTransactionError` when recipients cannot be resolved and
the intent is not a known no-recipient type. This is the remediation for
Trail of Bits finding TOB-BITGOEDMPC-1 (WCI-1100): the EdDSA MPCv2
re-sign path previously substituted an empty-recipients object, allowing
`verifyTransaction` to be bypassed on coins that only validate when
recipients are non-empty (SOL, VET, Tempo, TRON).

ECDSA already used this pattern (ecdsaMPCv2.ts:958,965); this ports it
to EdDSA MPCv2. MPCv1 (eddsa.ts) is explicitly out of scope.

Also removes the now-redundant EdDSA MPCv2 pre-fetch block from
`wallet.ts:signTransactionTss` and the matching pre-derivation in
`BaseTssUtils.recreateTxRequest`, along with the `txParamsFromIntent`
helper function they both called. `resolveEffectiveTxParams` inside
`signRequestBase` now owns intent-based recipient derivation, so the
wallet layer no longer needs to pre-derive before calling `signTxRequest`.

Ticket: WCI-1111
Session-Id: 1c178dac-6528-4ee7-937d-974216871d68
Task-Id: e91df1ba-6cf4-4b0c-8df2-2588f555481e
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 8e11038 to 1ecc1f5 Compare August 3, 2026 10:10
@ralph-bitgo
ralph-bitgo Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch 2 times, most recently from f524fa0 to 85b5bb8 Compare August 3, 2026 11:29
@bitgo-ai-agent-dev
bitgo-ai-agent-dev Bot force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from 85b5bb8 to ddc5199 Compare August 3, 2026 11:29
SOL authorize stake account operations (intentType 'authorize') have no
explicit transfer recipient. Without this entry, resolveEffectiveTxParams
would throw InvalidTransactionError when signing an authorize transaction
with no buildParams.

Ticket: WCI-1111
Session-Id: 1c178dac-6528-4ee7-937d-974216871d68
Task-Id: e91df1ba-6cf4-4b0c-8df2-2588f555481e
@Marzooqa
Marzooqa force-pushed the wci-1111-wire-resolve-effective-tx-params-eddsa branch from ddc5199 to fba4bbd Compare August 3, 2026 12:18
@Marzooqa
Marzooqa marked this pull request as ready for review August 3, 2026 12:58
@Marzooqa
Marzooqa requested review from a team as code owners August 3, 2026 12: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.

1 participant