Skip to content

fix: WALLET-1364 — close the P3 residual - #1466

Open
ost-ptk wants to merge 8 commits into
WALLET-1364-test-coverage-gapsfrom
WALLET-1364-p3-residual
Open

fix: WALLET-1364 — close the P3 residual#1466
ost-ptk wants to merge 8 commits into
WALLET-1364-test-coverage-gapsfrom
WALLET-1364-p3-residual

Conversation

@ost-ptk

@ost-ptk ost-ptk commented Aug 13, 2026

Copy link
Copy Markdown
Member

Closes the six residual P3 defects recorded in WALLET-1364. Stacked on #1465 — review that one
first; this branch builds on the runKeysDownload extraction it introduces.

Jira: https://make-software.atlassian.net/browse/WALLET-1364

What each change removes

# Defect What the user experienced
10 Account mutations waited out the re-encrypt debounce A browser quit or MV3 worker kill inside the 500 ms window dropped the last vault mutation. When that was an imported account, the secret key was gone — it exists nowhere else. The four account-mutating actions now persist immediately via takeEvery; everything re-derivable or cosmetic stays debounced.
11 A failed password change looked exactly like a successful one navigate(Home) sat outside both worker callbacks and ran unconditionally. The user landed on Home believing their password had changed when it had not. Navigation now happens only in onmessage; onerror shows a field error and stays put.
12 Unlock worker errors said nothing Both onerror handlers stopped the spinner with no message — indistinguishable from a wrong password, which the same screen reports properly a few lines above.
13 A partial key archive was presented as success Accounts whose createAsymmetricKeys returned secretKey: null were silently omitted from the zip while Success was shown. Now the export fails loudly, before anything is written to disk, and logs a count only.
14 Password hash compared with === Short-circuits at the first differing character. Now a constant-time comparison over the decoded bytes.
16 Non-Chrome style-src had no 'self' A source list of only 'unsafe-inline' matches no external stylesheet, and every app template links /assets/fonts/fonts.css. Fixed in webpack.config.js and in Safari's hand-maintained runtime CSP in src/utils.ts, which had drifted the same way.

Item 15 (QR sync uses AES-CBC with no MAC) is deliberately not fixed — see below.

Two things a review found that are worth your attention

A watch account used to break the whole export. Watch accounts are stored with secretKey: ''
and no hardware flag, so they passed the export list's !account.hardware filter. Item 13's
fail-loudly rule then meant a user with three real accounts and one watch account got no archive
at all
. That is worse than the bug being fixed, so the export list now excludes accounts with
nothing to export (selectVaultAccountsAvailableForExport), and the hard failure is reserved for a
genuinely unexpected null — data corruption, which should still never be shown as success.

Change-password now waits for the worker, so it needed a submitting state. Navigation correctly
moved inside onmessage, which leaves the page on screen for the worker's two scrypt passes
(N=2¹⁸, roughly 1-2 s). Without a guard, two taps spawn two ~256 MB scrypt workers in the popup.
It now mirrors the isSubmitting pattern already used by password-protection-page.

Limitations, stated rather than buried

  • The constant-time property is not test-enforceable here. Mutating the loop to break on the
    first mismatch does not change the output — |= is monotonic — only the timing. The tests prove
    the comparison is correct; the in-code comment is the only thing standing between a future edit
    and a reintroduced short-circuit. Worth knowing before touching that loop.
  • The two React paths have no automated coverage. This project's jest runs
    testEnvironment: 'node' with no jsdom, so change-password and unlock-vault cannot be
    unit-tested. Code reading was the only verification. Items to click through are listed below.
  • change-password disables the submit button while the worker runs, but unlike its sibling
    password-protection-page it does not also guard Enter re-submission or make the field
    read-only. The button guard covers the double-tap vector the review raised; the parity gap is
    noted rather than closed here.
  • password-protection-page's own worker.onerror is still silent. It was scoped out of the
    ticket, so two of the three password screens now report worker failure and one does not.
  • The new string Something went wrong. Please try again. has no catalogue entry, so the eight
    non-English locales fall back to English. locale:extract_pot was deliberately not run — lang/
    is hundreds of msgids behind and regenerating it would swamp this diff. A shorter
    Something went wrong already exists in four places; consolidating is a reasonable follow-up.

Why item 15 is not here

generate-sync-wallet-qr-data-worker.ts still uses AES-CBC with no MAC. The format is a
cross-application contract: casper-wallet-mobile/src/utils/aes/index.ts decrypts it with
aes-256-cbc and identical scrypt parameters (N = 2¹⁸, r = 8, p = 1, dkLen = 32), and its
react-native-aes-crypto exposes CBC only. Changing the extension alone breaks wallet sync until a
matching mobile release ships. The residual risk is also narrow — the ciphertext travels from the
user's own screen to their own camera. If picked up, it needs a versioned envelope landed on mobile
first.

Please verify before merging

The CSP change needs a real browser, which is the one thing this branch cannot settle itself:

  1. npm run build:firefox, load build/firefox via about:debugging, open the popup and the
    onboarding page, and check the console for a blocked-stylesheet violation on fonts.css
    before and after. Same for the Safari build.
  2. Change password: confirm it lands on Home only after the worker finishes, and that the button is
    disabled while it runs.
  3. Export keys with a watch account present, using "select all" — the watch account should not be
    offered at all.

npm run ci-check is green: 90 suites, 881 tests.

@ost-ptk ost-ptk changed the title WALLET 1364 p3 residual fix: WALLET-1364 — close the P3 residual Aug 13, 2026
@ost-ptk
ost-ptk requested a review from Comp0te August 14, 2026 08:27
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.

1 participant