[BWS][BWC][CWC] Bind prePublishRaw fallback to the proposal - #4232
Open
leolambo wants to merge 1 commit into
Open
[BWS][BWC][CWC] Bind prePublishRaw fallback to the proposal#4232leolambo wants to merge 1 commit into
leolambo wants to merge 1 commit into
Conversation
Verifier.checkTxProposalSignature falls back to txp.prePublishRaw when the locally-rebuilt tx does not match the creator's signature. It only checked that the signature was valid over prePublishRaw, never that prePublishRaw described the proposal being verified. A compromised server could pair a valid (prePublishRaw, proposalSignature) with a tampered destination and the check still passed. Bind prePublishRaw to the proposal. Recover the single field the server mutates at publish -- the Solana recent blockhash or the EVM/XRP nonce -- from prePublishRaw, rebuild the current proposal with that value substituted, and require a byte-for-byte match. Any other difference (destination, amount, from, contract) now fails as SERVER_COMPROMISED. Non-mutable chains (UTXO) reject prePublishRaw outright. The same guard is applied to the server-side publishTx fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
leolambo
marked this pull request as ready for review
August 28, 2026 19:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The transaction verifier falls back to
txp.prePublishRawwhen it can't match the creator's signature against the locally rebuilt tx. It only checked that the signature was valid overprePublishRaw, not thatprePublishRawwas the same proposal, so a compromised wallet service could keep a valid signature, swap the destination, and still pass the check. The fallback now recovers the one field the server changes at publish (the Solana blockhash or the EVM/XRP nonce) fromprePublishRaw, puts it back on the current proposal, and requires a byte-for-byte match, so any other change fails as SERVER_COMPROMISED.Changelog
prePublishRawand require the rebuilt proposal to match it exactly, so a tampered destination or amount fails as SERVER_COMPROMISED.prePublishRawon UTXO chains, which never mutate a field at publish.publishTxfallback the same way, so a tampered stored proposal can't reuse an old signature.getMutableFieldsto the SOL, EVM, and XRP providers to pull that field back out of a raw tx.Testing Notes
New tests at each layer:
getMutableFieldsrecovery for SOL, EVM, and XRPcheckPrePublishRawaccepts a refreshed field and rejects a tampered destinationisPrePublishRawBoundplus an end-to-endpublishTxthat rejects a tampered stored proposalRun
npm testin each of those three packages.Checklist
BWCif modifying the bitcore-wallet-client package,CLIif modifying the bitcore-cli package, etc.)