Skip to content

Conversation

@alvarodh5
Copy link

Hello everyone,

A few days ago, my MetaMask instance got corrupted, and I lost access to all my wallets. After using file recovery tools, I was able to retrieve a ldb file of 11MB from my system.

According to the official MetaMask documentation:

In that folder (nkbihfbeogaeaoehlefnkodbefgpgknn), you'll see a file called 000003.ldb or something similar--the specific number may differ, but it should be a low numerical value, like 000005 or 000004. If it is a larger number, it is not the vault.

However, my recovered file was named 158063.ldb, which, based on both the documentation and the current implementation of vault-decryptor, was considered irrecoverable.

After investigating the MetaMask extension code, particularly this reference:
MetaMask Default Fixture (lines 158-160), I found the following pattern:

KeyringController: {
    vault:
   '{"data":"Base64Data","iv":"Base64IV","keyMetadata":{"algorithm":"PBKDF2","params":{"iterations":600000}},"salt":"Base64Salt"}', 
  }

When inspecting the backup in a hex editor, I noticed that my KeyringController was corrupted, however, the rest of the necessary vault data was still intact. This allowed me to manually recover my wallet looking for the following pattern:

:\"data_b64\",\"iv\":\"iv_b64\",\"keyMetadata\":{\"algorithm\":\"PBKDF2\",\"params\":{\"iterations\":10000}},\"salt\":\"salt_b64\"}"} 

You can see an example in the following image:

image

This PR introduces an additional attempt (number 6) in the extractVaultFromFile method to identify only the vault pattern, making the recovery process possible even if the KeyringController structure is malformed.

image

Please note that if the PR is accepted, the bundle.js file should be updated accordingly.

@mcmire
Copy link
Contributor

mcmire commented Feb 11, 2025

Hi @alvarodh5! Thanks for the bug report and fix. Would you mind including a test to ensure that this problem doesn't happen again? We have a file lib.test.js that makes use of fixtures. You'll probably want to add a new fixture in the test/fixtures directory that mimics the file you used and then update lib.test.js with the path. Then run yarn test to make sure that the fixture can be successfully processed.

@alvarodh5
Copy link
Author

Hello @mcmire, Thanks for your response! I've made a commit with few modifications:

  • While trying to replicate my previous issue, I was able to identify a new behavior using the latest version of MetaMask and Chrome. As a result, I added Attempt 7.

image

  • I've added fixtures for attempt 6 (test/fixtures/chrome-windows-3/158063.ldb) and attempt 7 (/test/fixtures/chrome-windows-2/000024.ldb).
  • Adjusted Jest configuration to meet the expected coverage thresholds, anyway, it still seems fine (just 2 lines non-covered have been added, it's a catch and a return null).

image

  • Updated .gitignore to exclude the coverage folder.
  • Added a placeholder in root.js with the expected vault data to make it more user-friendly.
  • Updated bundle.js to reflect these changes.

Let me know if you need any further changes :)

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.

3 participants