Skip to content

feat(seedless-onboarding-controller): add password envelope encryption and recovery flow - #11346

Draft
ieow wants to merge 12 commits into
mainfrom
cw/seedless-password-envelope-main
Draft

ieow wants to merge 12 commits into
mainfrom
cw/seedless-password-envelope-main

Conversation

@ieow

@ieow ieow commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Explanation

Envelope-managed vaults let a user recover their secret data with a Recovery Secret instead of the global password, and let the password change without re-encrypting the vault keys.

This PR adds:

  • Envelope encryption (src/envelope/): EnvelopeStore persists encrypted envelope and control records in their own metadata partitions. envelope-keys derives and seals/opens the envelope keys. pending-migration checkpoints an in-flight migration so a failed call can be retried with the same bytes.
  • Migration: migrateToEnvelope makes the current vault keys the stable vault key set, seals them for the Recovery Secret, and writes a control record. Secret data items and the vault itself are unchanged. The first changePassword after migration writes the password envelope.
  • Recovery: authenticateForRecovery starts an aal2 recovery session (src/mfa-recovery/recovery-session.ts, held in non-persisted recoverySession state). recoverWithRecoverySecret opens the Recovery Secret envelope, fetches secret data, and creates a local vault under a new password. Until that password is synced or reset, it is treated as outdated.
  • Password reset without the old password: resetPasswordWithVaultKeys sets a new global password on an unlocked, envelope-managed vault after a Recovery Secret recovery. It is only allowed while envelope.passwordAuthPubKey is unset and with a valid aal2 session.
  • Existing flows: changePassword, syncLatestGlobalPassword, submitGlobalPassword, fetchAllSecretData, and checkIsPasswordOutdated now read envelope state first and fall back to the existing key chain when no envelope exists. Envelope-managed vaults are restored in fetchAllSecretData.
  • New messenger actions, error messages, and the EnvelopeState and RecoverySession types, all exported from src/index.ts.

Recovery flow:

flowchart TD
  A[Unlocked vault, aal2 via authenticateForRecovery] --> B[migrateToEnvelope]
  B --> C[(Envelope and control records in metadata)]
  C --> D[Password lost or forgotten]
  D --> E[recoverWithRecoverySecret]
  E --> F[Create local vault under new password]
  F --> G[resetPasswordWithVaultKeys or syncLatestGlobalPassword]
Loading

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

High Risk
Changes core vault encryption, password sync, and multi-device recovery with new MFA (aal2) paths—mistakes could lock users out or mishandle secret metadata.

Overview
Adds envelope-managed vaults to seedless onboarding: vault keys stay stable in metadata while passwords and a Recovery Secret each get sealed key envelopes plus a chained control record.

New messenger actions cover the full flow: authenticateForRecovery (aal2 recovery session), migrateToEnvelope (checkpointed migration), recoverWithRecoverySecret (restore without global password), and resetPasswordWithVaultKeys (set global password after recovery without the old one). State gains persisted envelope / pendingEnvelopeMigration and ephemeral recoverySession, with new error types for aal2, envelope, and recovery conflicts.

Existing password paths now prefer opening the password envelope (or detecting envelope status via control records) before the legacy TOPRF key chain: changePassword on envelope vaults only updates the password envelope and OPRF key under a metadata lock; syncLatestGlobalPassword, submitGlobalPassword, fetchAllSecretData, and checkIsPasswordOutdated follow the same envelope-first rules. Heavy SeedlessOnboardingController.envelope.test.ts coverage accompanies refactored shared test helpers; @metamask/auth-network-utils is bumped to ^0.4.0.

Reviewed by Cursor Bugbot for commit 2703265. Bugbot is set up for automated code reviews on this repo. Configure here.

ieow and others added 6 commits November 5, 2026 00:01
Adopt the current vault keys as a stable vault key set, sealed for the
password and for the Recovery Secret in their own metadata partitions,
with a control record holding the password namespace auth key.

- Add authenticateForRecovery and the non-persisted recoverySession
  state for the aal2 recovery verifier session
- Add migrateToEnvelope with a resumable, encrypted checkpoint
- Change the password of envelope-managed vaults by resealing the vault
  keys and swapping the password OPRF key under the metadata lock
- Open the password envelope first in syncLatestGlobalPassword and
  submitGlobalPassword
- Bump @metamask/auth-network-utils to ^0.4.0

Co-authored-by: Cursor <cursoragent@cursor.com>
…in fetchAllSecretData

Open the envelope sealed for the password before falling back to the
password's own keys, so a new device can restore after an envelope
password change.

Co-authored-by: Cursor <cursoragent@cursor.com>
…d envelope management

Refactor the handling of control records in the Seedless Onboarding Controller to support multiple control records instead of a single control item. This includes changes to how control records are fetched, written, and serialized, enhancing the management of envelope states and improving the overall migration process.

- Replace `ControlItem` with `ControlRecord` throughout the codebase.
- Update methods to handle arrays of control records, ensuring compatibility with the new structure.
- Modify the changelog to reflect the changes in how vault keys are sealed and managed under the new envelope system.

This update lays the groundwork for improved envelope management and recovery processes in future implementations.
… reset actions

Add new functionalities to the Seedless Onboarding Controller, including:
- `recoverWithRecoverySecret`: Allows recovery of an envelope-managed vault using a Recovery Secret instead of a password, enhancing user recovery options.
- `resetPasswordWithVaultKeys`: Enables setting a new global password on an unlocked, envelope-managed vault without requiring the old password.

Additionally, update error handling to include new messages related to recovery processes and adjust the changelog to reflect these changes. This update improves the overall user experience during vault recovery and password management.
…recovery processes

Refactor the Seedless Onboarding Controller to streamline the migration to envelope encryption. Key changes include:

- Simplified `migrateToEnvelope` method to eliminate the need for a password during migration, allowing the current password to derive the vault keys directly.
- Updated handling of control records to support multiple records and improve envelope management.
- Introduced new error handling for recovery processes, including clearer messaging for envelope-related issues.
- Adjusted tests to reflect changes in the migration process and ensure proper functionality.

These enhancements improve user experience during vault recovery and password management, aligning with ongoing efforts to optimize the onboarding process.
…ality and error handling

This update introduces improvements to the `resetPasswordWithVaultKeys` action within the Seedless Onboarding Controller. Key changes include:

- Clarified conditions under which the password can be reset, specifically requiring a valid aal2 session and ensuring the local password is not synced.
- Added new error messages, including `PasswordResetRequiresRecovery`, to provide clearer feedback during the password reset process.
- Updated documentation and tests to reflect these changes, ensuring robust error handling and user guidance.

These enhancements aim to streamline the password management experience and improve overall user interaction with the recovery process.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread package.json Resolved
@ieow ieow changed the title Cw/seedless password envelope main feat(seedless-onboarding-controller): add password envelope encryption and recovery flow Nov 6, 2026
…and update dependencies

This commit introduces significant changes to the Seedless Onboarding Controller, focusing on the handling of envelope keys. Key updates include:

- Replaced the `deriveEnvelopeKeys` function with `deriveTestEnvelopeKeys` to standardize envelope key derivation across the codebase.
- Updated various methods to utilize the new envelope key structure, ensuring consistency in how keys are managed and accessed.
- Adjusted tests to reflect these changes, enhancing the reliability of the testing suite.
- Updated the `yarn.lock` file to reflect changes in package dependencies.

These modifications aim to improve the overall architecture of the envelope management system and streamline the onboarding process for users.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

ieow and others added 3 commits November 6, 2026 18:07
…carding pending envelope migration

This update introduces a new behavior in the `recoverWithRecoverySecret` action, ensuring that any pending envelope migration checkpoint is discarded when a vault is restored using the Recovery Secret. Additionally, tests have been added to verify that the recovery session is maintained while the pending migration is cleared. Documentation has been updated to reflect these changes, improving clarity around the recovery process and its implications for envelope management.
…tarball

Co-authored-by: Cursor <cursoragent@cursor.com>
@ieow

ieow commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

…package.json` and update its reference in `yarn.lock` to use a local tarball instead of a portal link. This change ensures consistency in package management and resolves potential issues with package resolution.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a8247e6. Configure here.

Comment thread yarn.lock
checksum: 10/2714a70eae53a1f46d293980c71a1ed2f59708247019444154e71fc15328e78ec95287ffc2d954a29f903224a1a9fe4d69fb17724e9039bcefd240752f1df26c
checksum: 10/3b7d596185f54672f4e024f9088a70876ba59b036c1375da0e9f5dbcd2f44d81f81eaaa4b4eb9dbde6d74864c49a261a4960b044053364c64261fd80bf0fa270
languageName: node
linkType: hard

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Gitignored tarball breaks dependency install

High Severity

Removing the portal resolution makes Yarn resolve @metamask/toprf-secure-backup from metamask-toprf-secure-backup-1.1.0.tgz. That archive is excluded by the root *.tgz gitignore and is not in this commit, so yarn install fails for CI and anyone without the local file.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a8247e6. Configure here.

…gration behavior

Added documentation to the `SeedlessOnboardingControllerMigrateToEnvelopeAction` type, specifying that any pending envelope migration checkpoint will be discarded when this action is called, as it pertains to the vault being replaced. This enhances clarity regarding the migration process and its implications for existing checkpoints.
@ieow

ieow commented Nov 10, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@11.2.0-preview-270326558
@metamask-previews/accounts-controller@40.2.0-preview-270326558
@metamask-previews/address-book-controller@8.0.0-preview-270326558
@metamask-previews/advanced-chart-core@1.1.0-preview-270326558
@metamask-previews/ai-controllers@2.0.0-preview-270326558
@metamask-previews/analytics-controller@4.3.0-preview-270326558
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-270326558
@metamask-previews/announcement-controller@9.0.0-preview-270326558
@metamask-previews/app-metadata-controller@3.0.0-preview-270326558
@metamask-previews/approval-controller@10.0.0-preview-270326558
@metamask-previews/assets-controller@20.3.1-preview-270326558
@metamask-previews/assets-controllers@113.3.1-preview-270326558
@metamask-previews/authenticated-user-storage@4.1.0-preview-270326558
@metamask-previews/base-controller@10.1.0-preview-270326558
@metamask-previews/base-data-service@2.1.0-preview-270326558
@metamask-previews/bitcoin-regtest-up@2.0.0-preview-270326558
@metamask-previews/bridge-controller@83.1.4-preview-270326558
@metamask-previews/bridge-status-controller@78.0.2-preview-270326558
@metamask-previews/build-utils@4.0.0-preview-270326558
@metamask-previews/byte-utils@0.1.0-preview-270326558
@metamask-previews/chain-agnostic-permission@2.1.0-preview-270326558
@metamask-previews/chomp-api-service@7.0.0-preview-270326558
@metamask-previews/claims-controller@1.1.0-preview-270326558
@metamask-previews/client-controller@2.0.0-preview-270326558
@metamask-previews/client-utils@3.2.0-preview-270326558
@metamask-previews/compliance-controller@3.0.0-preview-270326558
@metamask-previews/composable-controller@13.0.0-preview-270326558
@metamask-previews/config-registry-controller@5.0.0-preview-270326558
@metamask-previews/connectivity-controller@1.0.0-preview-270326558
@metamask-previews/controller-utils@13.0.0-preview-270326558
@metamask-previews/core-backend@14.0.0-preview-270326558
@metamask-previews/cryptography@1.1.2-preview-270326558
@metamask-previews/delegation-controller@4.0.0-preview-270326558
@metamask-previews/earn-controller@13.1.0-preview-270326558
@metamask-previews/eip-5792-middleware@4.1.0-preview-270326558
@metamask-previews/eip-7702-internal-rpc-middleware@1.0.0-preview-270326558
@metamask-previews/eip1193-permission-middleware@3.0.0-preview-270326558
@metamask-previews/error-utils@0.1.0-preview-270326558
@metamask-previews/eth-block-tracker@16.0.0-preview-270326558
@metamask-previews/eth-json-rpc-middleware@26.0.0-preview-270326558
@metamask-previews/eth-json-rpc-provider@7.0.0-preview-270326558
@metamask-previews/eth-sig-util@9.0.0-preview-270326558
@metamask-previews/foundryup@2.0.0-preview-270326558
@metamask-previews/gas-fee-controller@27.1.1-preview-270326558
@metamask-previews/gator-permissions-controller@6.1.1-preview-270326558
@metamask-previews/geolocation-controller@2.0.0-preview-270326558
@metamask-previews/java-tron-up@2.0.0-preview-270326558
@metamask-previews/json-rpc-engine@11.0.0-preview-270326558
@metamask-previews/json-rpc-middleware-stream@9.0.0-preview-270326558
@metamask-previews/key-tree@10.1.1-preview-270326558
@metamask-previews/keyring-controller@28.2.0-preview-270326558
@metamask-previews/kyc-controller@0.16.0-preview-270326558
@metamask-previews/local-node-utils@2.0.0-preview-270326558
@metamask-previews/logging-controller@10.0.0-preview-270326558
@metamask-previews/marketing-consent-controller@1.1.0-preview-270326558
@metamask-previews/message-manager@15.0.0-preview-270326558
@metamask-previews/messenger@3.0.0-preview-270326558
@metamask-previews/messenger-cli@1.0.0-preview-270326558
@metamask-previews/mfa-recovery-controller@0.0.0-preview-270326558
@metamask-previews/money-account-api-data-service@2.3.1-preview-270326558
@metamask-previews/money-account-balance-service@3.2.0-preview-270326558
@metamask-previews/money-account-controller@3.0.0-preview-270326558
@metamask-previews/money-account-lifecycle-controller@0.0.0-preview-270326558
@metamask-previews/money-account-mfa-whitelist@0.2.0-preview-270326558
@metamask-previews/money-account-upgrade-controller@6.0.1-preview-270326558
@metamask-previews/money-account-utils@2.2.0-preview-270326558
@metamask-previews/multichain-account-service@14.1.0-preview-270326558
@metamask-previews/multichain-api-middleware@5.1.0-preview-270326558
@metamask-previews/multichain-network-controller@4.1.1-preview-270326558
@metamask-previews/multichain-transactions-controller@8.0.0-preview-270326558
@metamask-previews/name-controller@10.0.0-preview-270326558
@metamask-previews/network-connection-banner-controller@1.1.0-preview-270326558
@metamask-previews/network-controller@38.0.0-preview-270326558
@metamask-previews/network-enablement-controller@7.1.1-preview-270326558
@metamask-previews/node-utils@0.1.0-preview-270326558
@metamask-previews/notification-services-controller@30.1.0-preview-270326558
@metamask-previews/passkey-controller@4.1.0-preview-270326558
@metamask-previews/permission-controller@14.1.0-preview-270326558
@metamask-previews/permission-log-controller@6.0.0-preview-270326558
@metamask-previews/perps-controller@22.3.0-preview-270326558
@metamask-previews/phishing-controller@18.3.0-preview-270326558
@metamask-previews/platform-api-docs@0.2.1-preview-270326558
@metamask-previews/polling-controller@17.0.0-preview-270326558
@metamask-previews/preferences-controller@24.0.0-preview-270326558
@metamask-previews/profile-controller@3.0.0-preview-270326558
@metamask-previews/profile-metrics-controller@5.2.1-preview-270326558
@metamask-previews/profile-sync-controller@36.1.0-preview-270326558
@metamask-previews/ramps-controller@29.0.0-preview-270326558
@metamask-previews/rate-limit-controller@8.0.0-preview-270326558
@metamask-previews/react-data-query@2.0.0-preview-270326558
@metamask-previews/remote-feature-flag-controller@7.0.0-preview-270326558
@metamask-previews/sample-controllers@6.1.0-preview-270326558
@metamask-previews/seedless-onboarding-controller@12.0.0-preview-270326558
@metamask-previews/selected-network-controller@27.1.0-preview-270326558
@metamask-previews/sentinel-api-service@2.1.0-preview-270326558
@metamask-previews/shield-controller@7.1.1-preview-270326558
@metamask-previews/signature-controller@40.1.0-preview-270326558
@metamask-previews/smart-transactions-controller@27.2.2-preview-270326558
@metamask-previews/snap-account-service@4.0.0-preview-270326558
@metamask-previews/social-controllers@3.20.0-preview-270326558
@metamask-previews/solana-test-validator-up@2.0.0-preview-270326558
@metamask-previews/stellar-quickstart-up@0.0.0-preview-270326558
@metamask-previews/storage-service@2.0.0-preview-270326558
@metamask-previews/subscription-controller@15.2.0-preview-270326558
@metamask-previews/transaction-controller@73.1.2-preview-270326558
@metamask-previews/transaction-pay-controller@31.1.0-preview-270326558
@metamask-previews/transaction-pay-middleware@2.0.2-preview-270326558
@metamask-previews/type-utils@0.1.0-preview-270326558
@metamask-previews/user-operation-controller@42.1.1-preview-270326558
@metamask-previews/utils@12.0.1-preview-270326558
@metamask-previews/wallet@21.0.1-preview-270326558
@metamask-previews/watch-only-account-service@0.1.0-preview-270326558

This branch has not been deployed

No deployments
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