fix: gate the chain switch and remember endpoints per network (closes #308)
wallet_switchEthereumChain was answered for any origin at all, with no connection check and no prompt, so any page could move the active chain and clear the [TESTNET] banner under a user who believed they were on Sepolia. It now takes the same allowedSites check the signing methods take and returns 4100 for an unconnected origin. The handler also awaits loadState() before it reads or moves the network. The MV3 worker populates nothing at module scope, so a worker revived by the page's own message held DEFAULT_STATE: the same-chain check compared against the wrong network, and the save wrote empty wallets, empty allowedSites and default endpoints over the user's stored profile, destroying every wallet in the extension. Also fixes #316. Endpoints are now remembered per network in a persisted networkEndpoints map, so a user running a local or private node no longer loses that url permanently to a public endpoint on every switch. A stored map must be an actual object; a primitive previously survived the load and made every switch fall back to the public default with no self-healing. Verified failing first: dropping only the added loadState() fails exactly the two cold-worker cases; reverting only the type guard fails exactly the string and number cases. Reverting both source files to next gives 12 failed / 751 passed.
This commit was merged in pull request #313.
This commit is contained in:
22
TODO.md
22
TODO.md
@@ -44,6 +44,28 @@ but the review is broader than any of them.
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-08-20: A web page can no longer switch the wallet's chain, and switching
|
||||
no longer destroys the user's endpoints
|
||||
([#308](https://git.eeqj.de/sneak/AutistMask/issues/308)).
|
||||
`wallet_switchEthereumChain` was answered for any origin at all, with no
|
||||
connection check and no prompt: any page could clear the `[TESTNET]` banner
|
||||
under a user who believed they were on Sepolia. It now takes the same
|
||||
`allowedSites`/`connectedSites` gate the signing methods take, ahead of the
|
||||
same-chain and unsupported-chain answers, and refuses an unconnected origin
|
||||
with `4100`. The switch itself also overwrote `state.rpcUrl` and
|
||||
`state.blockscoutUrl` with the network defaults, so a user running their own
|
||||
node lost that url permanently and silently to a public endpoint that then
|
||||
sees every address they hold. Endpoints are now remembered per network in
|
||||
`state.networkEndpoints`, snapshotted from the network being left and restored
|
||||
for the network being entered; `state.rpcUrl` stays the live value for the
|
||||
active network, so no reader changed. A profile written before the map existed
|
||||
has its stored pair adopted for the network it was stored under, and loses
|
||||
nothing. The handler now loads state before it switches
|
||||
([#316](https://git.eeqj.de/sneak/AutistMask/issues/316)): the service worker
|
||||
populates nothing at module scope, so a worker revived by the page's own
|
||||
message held `DEFAULT_STATE`, and the switch persisted every field of it —
|
||||
wiping every wallet, every site approval and every tracked token from storage
|
||||
along with the endpoint.
|
||||
- 2026-08-20: The wallet's own ERC-20 send signs the amount it displayed
|
||||
([#305](https://git.eeqj.de/sneak/AutistMask/issues/305)). The confirmation
|
||||
screen renders from the block explorer's cached decimals; the transfer was
|
||||
|
||||
Reference in New Issue
Block a user