Repository navigation
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
|
75fd87b to
ad82f84
Compare
Approving a message-sign PA (WalletConnect personal_sign / EIP-712) crashed with 'TypeError: Cannot read properties of undefined (reading unsignedTx)' because postApprove() unconditionally runs the TSS recreate-and-sign flow, which reads transactions[0].unsignedTx — message-only txRequests have an empty transactions array. postApprove() now checks the PA's echoed intent via the new isMessageSigningRequest() guard and returns early for signMessage / signTypedStructuredData, leaving the message to be signed separately via signAndSendMessageTxRequest once the approval resolves. Also hardens the three ecdsa signTxRequest assertions to check length > 0 instead of truthiness (an empty array is truthy), and types the transactionRequestFull info field on PendingApprovalInfo. Test: 3 new unit tests (signMessage, signTypedStructuredData skip auto-sign; payment intent keeps it). Full PA suite: 19 passing, 3 pre-existing failures. Refs: DEFI-961
ad82f84 to
0184678
Compare
ReviewThe fix is targeted and sensible. Skipping the auto recreate-and-sign for message-only approvals matches the root cause. The assert hardening turns a Must fix: internal information in comments
Suggestions
Good practices
No security or cryptographic concerns: no change to signing inputs, key handling or derivation. |
Problem
Approving a message-sign pending approval (WalletConnect
personal_sign/ EIP-712eth_signTypedData_v4) crashes the SDK with:The crash is invisible to the PA approval itself — the server-side PUT succeeds (the txRequest moves to
pendingDelivery), but the SDK'spostApprove()unconditionally runs the TSS recreate-and-sign flow forTRANSACTION_REQUEST_FULLPAs, which readstxRequest.transactions[0].unsignedTx.serializedTxHexviarecreateAndSignTSSTransaction→tssUtils.recreateTxRequest→signTxRequest. Message-only txRequests have an emptytransactionsarray (truthy, so the assert passes), makingtransactions[0]undefined and the.unsignedTxread a TypeError.Users see a scary "contact support@bitgo.com" error on a successful approval, then have to re-sign from the request's activity detail (which works because the sign path uses
signAndSendMessageTxRequest— the retail fix in bitgo-retail #10649).Reproduced in prod by emerick (Oct 27) on the retail Tasks page.
Root cause
PendingApproval.postApprove()had no check for message-only requests:The TSS signer's
ecdsa.tsassert checks truthiness (txRequest.transactions || txRequest.unsignedTxs) — an empty array is truthy, sotransactions[0]is undefined.Fix
postApprove()guard — newisMessageSigningRequest()helper reads the PA's echoedinfo.transactionRequestFull.intent.intentTypeand returns early forsignMessage/signTypedStructuredData, skipping the auto recreate-and-sign. The message is signed separately viasignAndSendMessageTxRequestonce the approval resolves.signTxRequestsites changed from truthiness tolength > 0, turning any future empty-array crash into a clear assertion error.PendingApprovalInfonow declarestransactionRequestFullwithintent, so the guard compiles without casts.Testing
modules/bitgo/test/v2/unit/pendingApproval.ts:signMessageintent → auto-sign skipped ✅signTypedStructuredDataintent → auto-sign skipped ✅paymentintent → auto-sign still runs (no false positive) ✅tsc --buildcleanAfter merge
Retail bumps its
@bitgo-beta/sdk-corepin — no retail code change needed (theApprovalApproveForm/useUpdatePendingApprovalMutationpath is correct; the fix is entirely SDK-side).Related