Files
AutistMask/TODO.md
sneak f37d52e04a
All checks were successful
check / check (push) Successful in 28s
security: decrypt and sign dApp approvals in the popup (closes #157)
The dApp transaction and signature approval paths sent the user's plaintext
password to the background over runtime.sendMessage and decrypted there. Both
now decrypt in the popup, where the password is typed, and put only the signed
artifact on the wire: the raw signed transaction, or the signature. Neither the
password, the recovery phrase, the xprv nor the private key crosses the
messaging boundary any more. This matches what the popup-side eth_sendTransaction
path in confirmTx.js already did.

The popup runs the same sequence ethers' own sendTransaction() runs internally
(populateTransaction, then signTransaction), so nonce, gas, fee and chain id
population are unchanged. The background keeps broadcast and approval
resolution, and when the popup cannot produce an artifact it reports the error
over the same message so the requesting page still gets a failure rather than
hanging.

Moving the secret out of the background must not turn the background into a
blind relay, so it re-derives the signer from the artifact and checks it
against the approval it is holding before acting: shared/approvalVerify.js
asserts that a raw transaction is the approved transaction signed by the
approved address, and that a signature covers the approved payload and recovers
to the approved address.

A wrong password is now caught in the popup before anything is sent, so it
fails with an inline full-sentence error and leaves the pending approval alive
to retry; previously it reached the background and destroyed the approval.
Rejection still resolves with EIP-1193 code 4001, and approvals still survive
popup close and reopen.

Removes the four standing TODO(security) markers, now that the flaw is gone.
2026-08-10 13:55:29 +00:00

5.6 KiB

Workflow

  • branch (from main)
  • do the work in Next Step
  • move Next Step to the top of Completed Steps
  • move the top item of Future Steps into Next Step
  • commit (TODO.md changes in the same commit as the work)
  • merge to main if the branch is not protected, otherwise open a PR
  • push

Status

pre-1.0, working towards the 1.0.0 milestone. Tagged v0.1.0 on 2026-02-27. No other branch is in flight: the settings About well landed as #145 on 2026-07-26 and scripts-to-rule-them-all landed as #148, so the scripts/ directory question is resolved. Full policy file set present. make check verified passing on main at 23aeae4 on 2026-08-09. The 1.0.0 backlog is filed as #149-#168. A real-browser end-to-end suite (make test-e2e) now sits alongside make check, which cannot see a runtime ReferenceError in a popup view.

Next Step

Land #149: make DEBUG a build-time constant that defaults to off, injected as the __BUILD_DEBUG__ esbuild define from AUTISTMASK_DEBUG=1, so a plain make build stops handing every newly created wallet the publicly committed test recovery phrase. Branch fix/issue-149-debug-build-flag; PR open, awaiting review.

Completed Steps

  • 2026-08-09: dApp approval signing moved into the popup — the password no longer crosses the extension messaging boundary; the background broadcasts and resolves approvals only, and verifies the signed artifact against the approval it holds (#157).
  • 2026-08-09: Containerized Chrome end-to-end harness (make test-e2e / script/test-e2e) driving the real popup with all network intercepted, plus the two used-but-not-imported crashes it caught: AddToken unreachable (#150) and TransactionDetail broken for every ERC-20 transfer (#151). Harness demonstrated failing before the fixes and passing after (#181). Interception covers the MV3 background service worker, not just the popup page, and a launch-time canary aborts the suite if worker traffic starts escaping.
  • 2026-08-09: Reviewed the repo end to end and filed the 1.0.0 backlog (#149-#168).
  • 2026-08-09: Test coverage for the address-poisoning defense in src/shared/transactions.js (#160)
  • 2026-07-26: About well in settings with build info, repo link and the version click easter egg (#145); proper view navigation stack (#146).
  • 2026-07-07 Adopted scripts-to-rule-them-all: script/ entrypoints, Makefile shims, README Entrypoints section (#148)
  • 2026-03-01: USD display suppressed on testnets (#142); estimated USD for ETH in approve-tx view (#141).
  • Sepolia testnet support (#137); etherscan links go to token-specific URLs (#136).
  • Transaction detail improvements: Type field and on-chain details (#130), txid-first reordering (#133), swap display corrections (#128), expanded confirm-tx warnings (#118).
  • Dark mode theme setting (Light/Dark/System) with contrast fixes (#126); timestamps include timezone offset (#120); layout shift audit, reserved space for error messages (#124).
  • Copy-flash visual feedback with timing tune (#113, #121); cross-wallet-type duplicate detection (#115).
  • 2026-02-27: v0.1.0 tagged.
  • 2026-02-24: Initial scaffolding: popup UI, BIP-39 wallet creation via ethers.js, wallet persistence, real ETH balances over RPC, ENS forward and reverse resolution.

Future Steps

  • Add ESLint to script/lint (#152). make check is prettier --check only and cannot catch undefined identifiers, which is how #150 and #151 shipped.
  • Decide the libsodium backend that actually ships (#182) and delete the single allowlist entry it owns in tests/e2e/harness.js.
  • Extend the end-to-end suite to the dApp approval signing path (EIP-1193 through the real content script, background worker and approval popup). That path needs a CDP-based route to background-worker console output first: Playwright exposes no error event for service workers, so an uncaught exception in the worker cannot fail the run today (worker network traffic is already covered). Decide separately whether docker-in-docker makes make test-e2e runnable in the Gitea workflow.
  • Make the Firefox target functional: Chrome callback APIs are used against the promise-only browser namespace (#153).
  • Send and transaction-flow correctness: gas fee excluded from the insufficient-balance check (#154), WaitTx 60s timeout overwriting a rendered success screen (#155), last-wallet deletion leaving inconsistent state (#156).
  • Security: plaintext password crossing the extension messaging boundary during dApp approvals (#157); MV3 service worker termination killing the background refresh and the 24h phishing list update (#158).
  • Test the crypto core — wallet.js derivation and vault.js encryption (#159) — and the address-poisoning defense in transactions.js (#160).
  • Wallet features for 1.0: show a wallet's recovery phrase behind the password (#161), delete an address from an HD wallet (#162).
  • Docs: docs/README.md contradicts the code on external services and names competitors (#163); README Screen Map omits three shipped screens (#164).
  • Owner decisions: Sepolia support versus "Non-Goals for 1.0", and isMetaMask naming a competitor in shipped code (#165).
  • Repo policy compliance sweep: test rerun pattern, yarn/npx, frozen lockfile, undocumented Makefile targets (#166).
  • Prune the 24 stale remote feature branches (#167).
  • Remove dead exports and de-duplicate copy-pasted view helpers (#168).
  • Pre-1.0 security review of the extension (key handling, DEBUG mode policy, RPC input validation) before any 1.0rc tag; #149 and #157 are parts of it, but the review is broader than either.
  • Cut 1.0.0 once the milestone is empty, then continue tagging as milestones land.