harden: a page-supplied transaction nonce is honoured and shown only as a bare number #404

Closed
opened 2026-09-21 20:37:56 +02:00 by clawbot · 2 comments
Collaborator

Severity: hardening.

Where. src/shared/approvalTx.js:54-66 (REQUEST_FIELDS includes nonce,
passed to populateTransaction); src/popup/views/approval.js:228 (the nonce is
rendered as a plain number).

What is wrong. A dApp can fix the nonce of the transaction the user is asked
to sign. A nonce equal to a pending transaction's, paired with the fee the page
also supplies, can replace that transaction; a nonce above the account's next
nonce strands the transaction behind a gap. The approval screen shows the nonce
as a bare number with nothing to say the site chose it.

Why it matters. A dApp can cancel or replace the user's own pending
transactions, or strand a signed one, without the user understanding that the
nonce was site-chosen.

Reproduction. From a connected page, eth_sendTransaction with an explicit
nonce equal to a pending transfer's nonce (and a higher fee) — after approval
the user's own transfer is replaced.

Acceptable. Ignore a page-supplied nonce and populate it from the network
(as most wallets do), or mark on the approval screen that the nonce was chosen by
the site and state the consequence.

Definition of done.

  • Either the page-supplied nonce is dropped and populated from the network,
    or the approval screen labels a site-chosen nonce and its effect.
  • A test asserts the chosen behaviour for a page that supplies a nonce.

Model: fable-5-1 (review); opus-4-8 (filing)

Severity: hardening. **Where.** `src/shared/approvalTx.js:54-66` (`REQUEST_FIELDS` includes `nonce`, passed to `populateTransaction`); `src/popup/views/approval.js:228` (the nonce is rendered as a plain number). **What is wrong.** A dApp can fix the nonce of the transaction the user is asked to sign. A nonce equal to a pending transaction's, paired with the fee the page also supplies, can replace that transaction; a nonce above the account's next nonce strands the transaction behind a gap. The approval screen shows the nonce as a bare number with nothing to say the site chose it. **Why it matters.** A dApp can cancel or replace the user's own pending transactions, or strand a signed one, without the user understanding that the nonce was site-chosen. **Reproduction.** From a connected page, `eth_sendTransaction` with an explicit `nonce` equal to a pending transfer's nonce (and a higher fee) — after approval the user's own transfer is replaced. **Acceptable.** Ignore a page-supplied nonce and populate it from the network (as most wallets do), or mark on the approval screen that the nonce was chosen by the site and state the consequence. **Definition of done.** - [ ] Either the page-supplied nonce is dropped and populated from the network, or the approval screen labels a site-chosen nonce and its effect. - [ ] A test asserts the chosen behaviour for a page that supplies a nonce. Model: fable-5-1 (review); opus-4-8 (filing)
Author
Collaborator

Plan. One PR on a branch cut from next, base next.

  • Of the issue's two acceptable fixes, take the first: a page-supplied nonce is dropped and the nonce is always populated from the network, as most wallets do. It removes the replace-or-strand risk instead of explaining it, and leaves nothing new on the approval screen.
  • nonce leaves the fields taken from the request in src/shared/approvalTx.js; the approval screen keeps showing the nonce that will actually be used.
  • Test: a page that supplies a nonce gets the network's next nonce in the transaction it signs, and the screen shows that one; it fails against current next.
  • Not touched: the dApp gas limit question in #207, which is the owner's.

Model: opus-5-5

Plan. One PR on a branch cut from `next`, base `next`. - Of the issue's two acceptable fixes, take the first: a page-supplied `nonce` is dropped and the nonce is always populated from the network, as most wallets do. It removes the replace-or-strand risk instead of explaining it, and leaves nothing new on the approval screen. - `nonce` leaves the fields taken from the request in `src/shared/approvalTx.js`; the approval screen keeps showing the nonce that will actually be used. - Test: a page that supplies a nonce gets the network's next nonce in the transaction it signs, and the screen shows that one; it fails against current `next`. - Not touched: the dApp gas limit question in https://git.eeqj.de/sneak/AutistMask/issues/207, which is the owner's. Model: opus-5-5
Author
Collaborator

Built in #434: a nonce the site supplies is ignored, and the transaction always gets the account's next nonce from the network, which is the nonce the approval screen shows and the popup signs. The gas limit is untouched (#207).

Model: opus-5-5

Built in https://git.eeqj.de/sneak/AutistMask/pulls/434: a nonce the site supplies is ignored, and the transaction always gets the account's next nonce from the network, which is the nonce the approval screen shows and the popup signs. The gas limit is untouched (https://git.eeqj.de/sneak/AutistMask/issues/207). Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#404