Skip to content

Fixes cross-wallet txp view - #4227

Open
MichaelAJay wants to merge 3 commits into
bitpay:masterfrom
MichaelAJay:fix/cross-wallet-txp-view
Open

Fixes cross-wallet txp view#4227
MichaelAJay wants to merge 3 commits into
bitpay:masterfrom
MichaelAJay:fix/cross-wallet-txp-view

Conversation

@MichaelAJay

Copy link
Copy Markdown
Contributor

Description

Fixes a cross-wallet transaction proposal disclosure in GET /v1/txproposalsbyhash/:txid/.

Previously, the endpoint looked up transaction proposals globally by txid. This allowed an authenticated copayer to retrieve another wallet’s proposal when its txid was known. The endpoint now scopes the database lookup to the authenticated wallet.

Foreign and unknown txids return the same existing HTTP 400 TX_NOT_FOUND response, while owner access and transaction-note behavior remain unchanged.

Changelog

  • Add a wallet-scoped fetchTxByHashForWallet storage method.
  • Use the authenticated wallet ID when retrieving transaction proposals by hash.
  • Preserve the global hash lookup used by internal wallet-identifier and blockchain-monitor consumers.
  • Add service-level and HTTP-route regression coverage for owner, foreign-wallet, and unknown txids.
  • Add storage coverage for duplicate txids across wallets and verify deterministic wallet-scoped results.

Testing Notes

Requires MongoDB on localhost:27017.

  • TypeScript compilation and changed-file ESLint checks pass.
  • Transaction-by-hash service and HTTP-route tests: 6 passing.
  • Storage suite: 18 passing.
  • The HTTP tests verify:
    • foreign wallet → HTTP 400 TX_NOT_FOUND with no owner data;
    • owner wallet → HTTP 200 with the full proposal;
    • foreign and unknown txids → indistinguishable error responses.
  • The owner service test verifies transaction notes remain available.
  • Full package suite: 1469 passing, 21 pending, with 2 failures in the pre-existing race-sensitive Locks tests; neither failure intersects this diff.

Checklist

  • I have read CONTRIBUTING.md and verified that this PR follows the guidelines and requirements outlined in it.

Copilot AI left a comment

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.

Pull request overview

This PR fixes an information disclosure in the Bitcore Wallet Service “tx proposal by hash” read path by scoping the storage lookup to the authenticated wallet, preventing a copayer from retrieving another wallet’s proposal when they know the txid.

Changes:

  • Adds a wallet-scoped storage lookup (fetchTxByHashForWallet) for tx proposals by txid.
  • Updates WalletService.getTxByHash to use the authenticated wallet ID for the by-hash lookup.
  • Adds regression tests covering same-wallet success and cross-wallet/unknown-txid non-disclosure at storage, service, and HTTP-route levels.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
packages/bitcore-wallet-service/src/lib/storage.ts Adds wallet-scoped tx-by-hash storage lookup used by authenticated reads.
packages/bitcore-wallet-service/src/lib/server.ts Switches getTxByHash to call the wallet-scoped storage method.
packages/bitcore-wallet-service/test/storage.test.ts Adds storage coverage for duplicate txids across wallets and wallet-scoped disambiguation.
packages/bitcore-wallet-service/test/integration/server.test.ts Adds service + HTTP-route regression tests ensuring foreign-wallet/unknown txids return indistinguishable not-found errors.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


// Wallet-scoped counterpart to fetchTxByHash, used by the authenticated
// by-hash API read.
fetchTxByHashForWallet(walletId: string, hash, cb: (err?: any, tx?: TxProposal) => void) {
@@ -3139,7 +3139,12 @@ export class WalletService implements IWalletService {
* @returns {Object} txProposal
*/
getTxByHash(opts, cb) {
Comment on lines +9180 to +9183
afterEach(function() {
verifyStub.restore();
httpServer.close();
});
disableLogs: true,
basePath: config.basePath
});
httpServer.listen(testPort);
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.

2 participants