fix: typed data for another chain cannot be signed (closes #519) #544

Merged
clawbot merged 1 commits from issue-519-typed-data-chain-id into next 2026-10-14 08:31:44 +02:00
Collaborator

Closes #519.

EIP-712 asks a wallet to refuse typed data whose domain chainId is not the active chain. Nothing checked it, so a wallet on Sepolia would sign a mainnet USDC permit.

  • The sign screen refuses it as it refuses a mismatched primary type: the reason on the error line (both chain ids and the active network's name), Sign disabled, and the Sign handler checks again.
  • The background checks again when the popup hands back the signature, against the network active at that moment, and answers the site with the same sentence instead of the signature. This also covers a network switch made while the prompt was open.
  • Both use typedDataChainRefusal() in src/shared/approvalVerify.js. It reads the chain id with ethers' getBigInt(), as ethers does when signing, so 1, "1" and "0x1" are one chain. A null or absent chainId is not refused, because ethers then signs no chain id. A chainId that is not a number gets the existing "cannot be read" sentence.

What the diff does not show:

  • The background's refusal spends the approval (not retryable), as an address switch does.
  • The sign-response handler now reads state once and takes the active address and the network from that one read, as the transaction path does.

Judgement call: the background refuses when the signature comes back, not when the site asks, so the user still sees the screen and the reason.

Model: opus-5-5

Closes https://git.eeqj.de/sneak/AutistMask/issues/519. EIP-712 asks a wallet to refuse typed data whose domain `chainId` is not the active chain. Nothing checked it, so a wallet on Sepolia would sign a mainnet USDC permit. - The sign screen refuses it as it refuses a mismatched primary type: the reason on the error line (both chain ids and the active network's name), Sign disabled, and the Sign handler checks again. - The background checks again when the popup hands back the signature, against the network active at that moment, and answers the site with the same sentence instead of the signature. This also covers a network switch made while the prompt was open. - Both use `typedDataChainRefusal()` in `src/shared/approvalVerify.js`. It reads the chain id with ethers' `getBigInt()`, as ethers does when signing, so `1`, `"1"` and `"0x1"` are one chain. A null or absent `chainId` is not refused, because ethers then signs no chain id. A `chainId` that is not a number gets the existing "cannot be read" sentence. What the diff does not show: - The background's refusal spends the approval (not retryable), as an address switch does. - The sign-response handler now reads state once and takes the active address and the network from that one read, as the transaction path does. Judgement call: the background refuses when the signature comes back, not when the site asks, so the user still sees the screen and the reason. Model: opus-5-5
clawbot added the needs-review label 2026-10-14 07:59:19 +02:00
clawbot self-assigned this 2026-10-14 07:59:19 +02:00
clawbot added 1 commit 2026-10-14 07:59:19 +02:00
fix: typed data for another chain cannot be signed (closes #519)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run
f9379d9fb9
EIP-712 has a wallet refuse typed data whose domain chainId is not the
active chain, because the signature is valid on the chain it names. The
sign screen now shows such a request with the reason on its error line
and Sign disabled, the same way it refuses a mismatched primary type.
The background checks again when the signature comes back, against the
network active then, and answers the site with that refusal instead of
the signature. A chain id is read as ethers signs it, so 1, "1" and
"0x1" are one chain. Typed data with no chainId signs as before.

Model: opus-5-5
Author
Collaborator

PASS: this meets every point of #519 on the head rebased onto the current next, with no findings.

Model: opus-5-5

PASS: this meets every point of https://git.eeqj.de/sneak/AutistMask/issues/519 on the head rebased onto the current `next`, with no findings. Model: opus-5-5
clawbot merged commit 83f3549d37 into next 2026-10-14 08:31:44 +02:00
clawbot deleted branch issue-519-typed-data-chain-id 2026-10-14 08:31:45 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#544