Repository navigation
fix(sdk-coin-xrp): include SendMax, Paths and DeliverMin in Payment explanation - #10161
Conversation
|
|
|
@claude review for logical correctness, implementation completeness and regressions |
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.
a43678c to
c48ea90
Compare
…xplanation Problem/goal: The Payment explanation returned only Destination, Amount and Fee, so SendMax, Paths and DeliverMin were not visible to consumers. Implementation details: - Both explainers (xrp.ts and lib/transaction.ts) now return sendMax, hasPaths and deliverMin when present, and list them in displayOrder. - Payments without these fields produce the same explanation as before. - No signing or verification behaviour changes. Verification: Added unit tests for explainer output in both explainers and for plain payments carrying no extra fields. sdk-coin-xrp unit suite passes (162 tests); tsc and eslint clean. Ticket: CSHLD-2162
c48ea90 to
05c7e45
Compare
|
@claude review |
|
Claude finished @mukeshsp's task in 24s —— View job Review of #10161No blocking issues. The change is small and does what the description says. I reviewed the diff against the current HEAD ( Correctness
Tests
Regressions
Earlier inline comments are stale
Optional
|
There was a problem hiding this comment.
Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.
Still open from earlier reviews (1):
- Unresolved: 1 minor or pre-existing.
Additional findings (outside the current diff — GitHub can't attach inline comments there):
-
🟣
modules/sdk-coin-xrp/src/xrp.ts— Pre-existing, security-relevant: a send can still pass verification when the prebuild spends a different asset than the one being sent. verifyTransaction now receives sendMax and hasPaths from the explainer but never reads them. It rejects onlypartialPayment(xrp.ts:552) and compares Destination and Amount (xrp.ts:583). Fix: for verified sends, rejecthasPaths,deliverMin, and anysendMaxwhose asset differs from Amount. Keep accepting the same-mpt_issuance_idSendMax that mptTransferBuilder.ts:132 sets to cover the MPT TransferFee.Why this was flagged
The trigger is a txPrebuild.txHex from the server (or a tampered one) for a
paymentsend. Its Destination and Amount match txParams.recipients[0]. It also carries SendMax set to the wallet's whole issued-currency balance (for example 100000 RLUSD) and Paths routed through offers the attacker controls. Xrp.verifyTransaction (xrp.ts:514) calls explainTransaction, which now returnssendMaxandhasPaths: true(xrp.ts:356, xrp.ts:384). verifyTransaction only checkspartialPayment(xrp.ts:552) and then runs the comparator on outputs[0] (xrp.ts:574-585), so it returns true. Once signed, the payment can spend up to SendMax of the other asset to deliver Amount, which drains that balance into the attacker's offers. The base branch behaves the same way: it has no SendMax/Paths check, and the PR says verification is unchanged. But this PR is what puts these fields into the explanation that verifyTransaction already reads. The partial-payment rejection follows the same logic ("BitGo never builds partial payments"), and BitGo's own builders never set Paths or a cross-asset SendMax.Verification: Nothing in verifyTransaction reads sendMax, hasPaths or deliverMin. It rejects only
explanation.partialPayment === true(xrp.ts:552-554) and then runscomparator(output, expectedOutput)(xrp.ts:583), which checks only the address and the numeric value of Amount. So a cross-currency Payment that can spend up to SendMax of another asset passes verification. Base 6aef749 has the same verifyTransaction body.
Problem
The Payment explanation returned only
Destination,AmountandFee, soSendMax,PathsandDeliverMinwere not visible to consumers.Changes (
modules/sdk-coin-xrp)xrp.tsandlib/transaction.ts) now returnsendMax,hasPathsanddeliverMinwhen present, and list them indisplayOrder.Verification
tscand eslint are clean.Ticket: CSHLD-2162