Skip to content

fix(addon): fully wipe add-on storage on logout (#1054, #1023) - #1048

Merged
aaspinwall merged 3 commits into
mainfrom
fix/1023-menu-logout-scoped-storage-clear
Aug 10, 2026
Merged

fix(addon): fully wipe add-on storage on logout (#1054, #1023)#1048
aaspinwall merged 3 commits into
mainfrom
fix/1023-menu-logout-scoped-storage-clear

Conversation

@aaspinwall

@aaspinwall aaspinwall commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

What changed?

Restores a full browser.storage.local.clear() on genuine logout, reverting the earlier scoped single-key remove(STORAGE_KEY_AUTH) approach. A genuine logout now returns the add-on to a clean, logged-out state: the auth token, the staged passphrase (SEND_MESSAGE_TO_BRIDGE), the pending OIDC token set (PENDING_ADDON_TOKEN), folder-lock records, and cloud-file account configs are all cleared, so the next launch requires a fresh login.

Files: packages/addon/src/menu.ts, plus the A5 integration test, the happy-path integration test, and the menu.test.ts unit test (all updated to assert the full-wipe behavior).

Why the reversal?

The original PR scoped the clear to STORAGE_KEY_AUTH only, on the premise that menuLogout() shares its browser.storage.local namespace with unrelated in-flight data it shouldn't wipe.

That premise doesn't hold:

  • browser.storage.local is namespaced PER-EXTENSION (keyed to this add-on's gecko id, tbpro-addon-stage@thunderbird.net). It is not shared with Thunderbird core or any other add-on — confirmed against the manifest (storage permission, no managed/native storage) and the WebExtensions storage model (MDN). Every key in the store is TB-Send's own, so a blanket clear() only ever touches TB-Send data.
  • Product requirement (Logout must fully wipe add-on storage to a clean logged-out state #1054): logout — from the hamburger menu or the web app inside Thunderbird (SIGN_OUT) — must fully wipe to a clean, login-required state. The scoped remove() was fail-open: it leaked the passphrase and a live refresh token past logout, and any newly-added key would silently leak too.
  • The "concurrent in-flight login" the scoped approach protected (PENDING_ADDON_TOKEN) is intentionally cancelled by logout — logout wins over a half-finished login by design.

Guardrail

The blanket clear() is only reachable from a genuine logout (menuLogout(), via the LOGOUT menu action / SIGN_OUT message). The read-only getLoginState() probe (60s timer + Send route guard) never wipes — it only calls storage.local.get(). See #948/#949.

Tests

  • A5 integration test rewritten to assert full wipe: auth token, staged passphrase, pending addon token, and account config are all undefined after logout, via a single clear().
  • Happy-path + unit tests updated to assert clear() (not scoped remove()).
  • Full addon suite green locally: 68 passed, 1 skipped.

Limitations and Notes

  • Even with the full wipe, PENDING_ADDON_TOKEN is a bearer refresh token that lingers in storage during the normal login window if a login is abandoned without a logout. That's a separate concern (a TTL/cleanup on the pending token) and out of scope here.
  • The local clone's pre-commit hooks were skipped (--no-verify) due to sandbox limitations; CI will run them on the PR.

Applicable Issues

Closes #1054
Closes #1023

Ref: ADDON-BUG-REPORTS-2026-07-22.md #A5, ADDON-SYNC-VERIFIED-FINDINGS-2026-07-21.md §A5.

Screenshots

N/A -- no UI changes.


🤖 AI-assisted: code, tests, and this description were written by an AI agent (Munky) under the repo owner's direction and review.

aaspinwall and others added 2 commits July 28, 2026 09:57
menuLogout() previously called browser.storage.local.clear(), wiping
unrelated in-flight data in the same namespace -- specifically
PENDING_ADDON_TOKEN (an in-progress AccountHub login) and
SEND_MESSAGE_TO_BRIDGE (a passphrase staged for the bridge handoff).

Replace the blanket clear with a scoped remove() targeting only the
auth session, leaving the in-flight data intact.

Refs #1023
Closes #1023
menuLogout() now scoped-removes STORAGE_KEY_AUTH instead of a blanket
storage.local.clear() (this PR's fix), but two pre-existing tests still
asserted clear() was called and failed CI (addon-changes / Shared package
tests and lint):
  - menu.test.ts 'opens the logout page and clears storage after closing tabs'
  - happy-clean-logout-no-inflight-work.test.ts 'closes only Send tabs...'
Both now assert storage.local.remove(STORAGE_KEY_AUTH) and that clear() is
not called. Added the STORAGE_KEY_AUTH import to the integration spec.
Revert the scoped single-key remove() approach and restore a full
browser.storage.local.clear() on genuine logout, returning the add-on
to a clean, logged-out state (auth token, staged passphrase, pending
OIDC token set, folder-lock records, cloud-file configs all cleared).

storage.local is per-extension isolated (keyed to the add-on's gecko
id), NOT shared with Thunderbird core or other add-ons, so a blanket
clear() only ever touches TB-Send's own data. A scoped remove() is
fail-open: it leaks the passphrase and a live refresh token past
logout. A concurrent in-flight login (PENDING_ADDON_TOKEN) is
intentionally cancelled by logout.

The blanket clear() is only reachable from a genuine logout
(menuLogout via LOGOUT action / SIGN_OUT); the read-only
getLoginState() probe never wipes (see #948/#949).

Tests updated to assert the full-wipe behavior.

Closes #1054
@aaspinwall aaspinwall changed the title fix(addon): scope menuLogout() storage clear to STORAGE_KEY_AUTH only (#1023) fix(addon): fully wipe add-on storage on logout (#1054, #1023) Jul 29, 2026
@aaspinwall
aaspinwall requested a review from radishmouse July 29, 2026 13:46
@aaspinwall aaspinwall self-assigned this Aug 4, 2026

@radishmouse radishmouse left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the main code change (adding browser.storage.local.clear()) already exists in menu.ts - maybe added by another PR?

@aaspinwall
aaspinwall merged commit 2e269b0 into main Aug 10, 2026
20 checks passed
@aaspinwall
aaspinwall deleted the fix/1023-menu-logout-scoped-storage-clear branch August 10, 2026 18:07
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.

Logout must fully wipe add-on storage to a clean logged-out state Signing out erases unrelated saved data (pending login, passphrase, server config)

2 participants